Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add VRRP checks for if instance is an owner. #37

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion holo-bgp/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,7 @@ where
let mut nbr_reach = reach.clone();
nbr_unreach.extend(
nbr_reach
.extract_if(|(_, route)| !nbr.distribute_filter(route))
.extract_if(.., |(_, route)| !nbr.distribute_filter(route))
.map(|(prefix, _)| prefix),
);

Expand Down
2 changes: 1 addition & 1 deletion holo-northbound/src/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ where
// Move to a separate vector the changes that need to be relayed.
let callbacks = P::callbacks().unwrap();
let relayed_changes = changes
.extract_if(|(cb_key, _)| !callbacks.0.contains_key(cb_key))
.extract_if(.., |(cb_key, _)| !callbacks.0.contains_key(cb_key))
.collect();

// Process local changes.
Expand Down
5 changes: 3 additions & 2 deletions holo-vrrp/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ pub(crate) fn process_vrrp_packet(
fsm::State::Master => {
let primary_addr = interface.system.addresses.first().unwrap().ip();
if packet.priority == 0 {
instance.send_vrrp_advertisement(primary_addr);
instance
.send_vrrp_advertisement(primary_addr, interface.system);
instance.timer_reset();
} else if packet.priority > instance.config.priority
|| (packet.priority == instance.config.priority
Expand Down Expand Up @@ -142,7 +143,7 @@ pub(crate) fn handle_master_down_timer(
};

// RFC 3768: Section 6.4.2 ("If the Master_Down_timer fires")
instance.send_vrrp_advertisement(src_ip);
instance.send_vrrp_advertisement(src_ip, interface.system);
instance.send_gratuitous_arp();
instance.change_state(
&interface,
Expand Down
39 changes: 33 additions & 6 deletions holo-vrrp/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,13 @@ impl Instance {
match InstanceNet::new(interface, &self.mvlan) {
Ok(net) => {
self.net = Some(net);
if self.config.priority == 255 {
let iface_system = &interface.system;
if self.config.priority == 255
|| self.check_is_owner(iface_system)
{
let src_ip =
interface.system.addresses.first().unwrap().ip();
self.send_vrrp_advertisement(src_ip);
self.send_vrrp_advertisement(src_ip, iface_system);
self.send_gratuitous_arp();
self.change_state(
interface,
Expand Down Expand Up @@ -285,6 +288,7 @@ impl Instance {
let task = tasks::advertisement_interval(
self,
src_ip,
interface.system,
&net.net_tx_packetp,
);
self.state.timer = VrrpTimer::AdvTimer(task);
Expand All @@ -308,17 +312,27 @@ impl Instance {
}
}

pub(crate) fn generate_vrrp_packet(&self) -> VrrpHdr {
pub(crate) fn generate_vrrp_packet(
&self,
iface_system: &InterfaceSys,
) -> VrrpHdr {
let mut ip_addresses: Vec<Ipv4Addr> = vec![];
for addr in &self.config.virtual_addresses {
ip_addresses.push(addr.ip());
}

// RFC 3768 -> 5.3.4. Priority
let priority = if self.check_is_owner(iface_system) {
255
} else {
self.config.priority
};

let mut packet = VrrpHdr {
version: 2,
hdr_type: 1,
vrid: self.vrid,
priority: self.config.priority,
priority,
count_ip: self.config.virtual_addresses.len() as u8,
auth_type: 0,
adver_int: self.config.advertise_interval,
Expand Down Expand Up @@ -360,10 +374,14 @@ impl Instance {
}
}

pub(crate) fn send_vrrp_advertisement(&mut self, src_ip: Ipv4Addr) {
pub(crate) fn send_vrrp_advertisement(
&mut self,
src_ip: Ipv4Addr,
iface_system: &InterfaceSys,
) {
let packet = VrrpPacket {
ip: self.generate_ipv4_packet(src_ip),
vrrp: self.generate_vrrp_packet(),
vrrp: self.generate_vrrp_packet(iface_system),
};
let msg = NetTxPacketMsg::Vrrp { packet };
let net = self.net.as_ref().unwrap();
Expand Down Expand Up @@ -403,6 +421,15 @@ impl Instance {
let _ = net.net_tx_packetp.send(msg);
}
}

/// An instance is an owner if all its virtual addresses are
/// also addresses part of the parent interface's IP addresses
pub(crate) fn check_is_owner(&self, interface_sys: &InterfaceSys) -> bool {
self.config
.virtual_addresses
.iter()
.all(|addr| interface_sys.addresses.contains(addr))
}
}

impl Drop for Instance {
Expand Down
5 changes: 2 additions & 3 deletions holo-vrrp/src/northbound/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,13 @@ fn load_callbacks() -> Callbacks<Interface> {
let iter = interface.instances.iter().map(|(vrid, instance)| ListEntry::Instance(*vrid, instance));
Some(Box::new(iter))
})
.get_object(|_interface, args| {
.get_object(|interface, args| {
use interfaces::interface::ipv4::vrrp::vrrp_instance::VrrpInstance;
let (vrid, instance) = args.list_entry.as_instance().unwrap();
Box::new(VrrpInstance {
vrid: *vrid,
state: Some(instance.state.state.to_yang()),
// TODO
is_owner: None,
is_owner: Some(instance.check_is_owner(&interface.system)),
last_adv_source: instance.state.last_adv_src.map(std::convert::Into::into).map(Cow::Owned).ignore_in_testing(),
up_datetime: instance.state.up_time.as_ref().map(Cow::Borrowed).ignore_in_testing(),
master_down_interval: instance.state.timer.as_master_down_timer().map(|task| task.remaining().as_millis() as u32 / 10).ignore_in_testing(),
Expand Down
4 changes: 3 additions & 1 deletion holo-vrrp/src/tasks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use messages::output::NetTxPacketMsg;
use tracing::{debug_span, Instrument};

use crate::instance::Instance;
use crate::interface::InterfaceSys;
use crate::network;
use crate::packet::VrrpPacket;

Expand Down Expand Up @@ -203,13 +204,14 @@ pub(crate) fn master_down_timer(
pub(crate) fn advertisement_interval(
instance: &Instance,
src_ip: Ipv4Addr,
iface_system: &InterfaceSys,
net_tx_packetp: &UnboundedSender<NetTxPacketMsg>,
) -> IntervalTask {
#[cfg(not(feature = "testing"))]
{
let packet = VrrpPacket {
ip: instance.generate_ipv4_packet(src_ip),
vrrp: instance.generate_vrrp_packet(),
vrrp: instance.generate_vrrp_packet(iface_system),
};
let adv_sent = instance.state.statistics.adv_sent.clone();
let net_tx_packetp = net_tx_packetp.clone();
Expand Down
Loading