Fix handling of seqno requests for local routes

Signed-off-by: Lee Smet <lee.smet@hotmail.com>
This commit is contained in:
Lee Smet
2023-11-07 18:11:49 +01:00
parent 1e6ebbc8fb
commit 0cdedb51e4
3 changed files with 72 additions and 30 deletions
+1
View File
@@ -137,6 +137,7 @@ impl Decoder for Codec {
TLV_TYPE_SEQNO_REQUEST => SeqNoRequest::from_bytes(src, body_len).map(From::from),
_ => {
// unrecoginized body type, silently drop
trace!("Dropping unrecognized tlv");
src.advance(header.body_length as usize - 1);
self.reset();
return Ok(None);
+70 -29
View File
@@ -28,7 +28,7 @@ const UPDATE_INTERVAL: u16 = HELLO_INTERVAL * 4;
const ROUTE_PROPAGATION_INTERVAL: u64 = 3;
const DEAD_PEER_TRESHOLD: u64 = 8;
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct StaticRoute {
subnet: Subnet,
}
@@ -387,7 +387,11 @@ impl Router {
|| !route_entry.seqno().lt(&seqno_request.seqno()))
{
// we have a more up to date route or a different route, send an update
debug!(
"Replying to seqno request for seqno {} of {} with update packet",
seqno_request.seqno(),
seqno_request.prefix()
);
drop(inner);
let update = babel::Update::new(
UPDATE_INTERVAL,
@@ -413,35 +417,44 @@ impl Router {
return;
}
}
// Otherwise, if the router id in the request matches the router id in our selected route
// and the requested sequence number is larger than the one on our selected route, compare
// the router id with our own router id. If it matches, bump our own sequence number by 1.
// At this point, we also send an update for the route (triggered update), to distribute
// the route.
if seqno_request.router_id() == route_entry.source().router_id()
&& seqno_request.seqno().gt(&route_entry.seqno())
&& seqno_request.router_id() == self.router_id
{
// Bump router seqno
// TODO: should we only send an update to the peer who sent the seqno request
// instad of updating all our peers?
drop(inner);
let mut inner_w = self.inner_w.lock().expect("Mutex isn't poisoned");
inner_w.append(RouterOpLogEntry::BumpSequenceNumber);
// We already need to publish here so the sequence number is set correctly when
// calling the method to propagate the static routes.
inner_w.publish();
// Otherwise, if the router id in the request matches the router id in our selected route
// and the requested sequence number is larger than the one on our selected route, compare
// the router id with our own router id. If it matches, bump our own sequence number by 1.
// At this point, we also send an update for the route (triggered update), to distribute
// the route.
//
// Note that we currently don't install local routes in the routing table and as such
// can't check on this. Therefore this condition is reworked. We always advertise local
// routes with the current router id and the current router seqno. So we check if the
// prefix is part of our static routes, if the router id is our own, and if the
// requested seqno is greater than our own.
if seqno_request.router_id() == self.router_id
&& seqno_request.seqno().gt(&inner.router_seqno)
&& inner.static_routes.contains(&StaticRoute {
subnet: seqno_request.prefix(),
})
{
// Bump router seqno
// TODO: should we only send an update to the peer who sent the seqno request
// instad of updating all our peers?
drop(inner);
let mut inner_w = self.inner_w.lock().expect("Mutex isn't poisoned");
debug!("Bumping local router sequence number");
inner_w.append(RouterOpLogEntry::BumpSequenceNumber);
// We already need to publish here so the sequence number is set correctly when
// calling the method to propagate the static routes.
inner_w.publish();
let ops = inner_w
.enter()
.expect("We enter through a write handle so this can never be None")
.propagate_static_route(self.router_id);
let ops = inner_w
.enter()
.expect("We enter through a write handle so this can never be None")
.propagate_static_route(self.router_id);
inner_w.extend(ops);
inner_w.publish();
return;
}
inner_w.extend(ops);
inner_w.publish();
return;
}
// Otherwise, if the router-id from the request is not our own, we check the hop count
@@ -458,6 +471,12 @@ impl Router {
// First only consider feasible routes.
for re in &possible_routes {
if !re.metric().is_infinite() && re.neighbour() != &source_peer {
debug!(
"Forwarding seqno request {} for {} to {}",
seqno_request.seqno(),
seqno_request.prefix(),
re.neighbour().underlay_ip()
);
if let Err(e) = re.neighbour().send_control_packet(seqno_request.into()) {
error!("Failed to foward seqno request: {e}");
}
@@ -468,6 +487,12 @@ impl Router {
// Finally consider infeasible routes as well.
for re in possible_routes {
if re.neighbour() != &source_peer {
debug!(
"Forwarding seqno request {} for {} to {}",
seqno_request.seqno(),
seqno_request.prefix(),
re.neighbour().underlay_ip()
);
if let Err(e) = re.neighbour().send_control_packet(seqno_request.into()) {
error!("Failed to foward seqno request: {e}");
}
@@ -523,6 +548,15 @@ impl Router {
)
};
debug!(
"Got update packet from {} for subnet {} with metric {} and seqno {} and router-id {}. Route entry exists: {route_entry_exists} and update is feasible: {update_feasible}",
source_peer.underlay_ip(),
update.subnet(),
update.metric(),
update.seqno(),
update.router_id()
);
// if no entry exists (based on prefix, plen AND neighbor field)
if !route_entry_exists {
if metric.is_infinite() || !update_feasible {
@@ -604,6 +638,7 @@ impl Router {
inner_w.append(RouterOpLogEntry::RemoveSourceEntry(source_key));
return;
}
let possible_entry = inner_w
.enter()
.expect("We deref through a write handle so this enter never fails")
@@ -628,7 +663,12 @@ impl Router {
)
});
debug!("Sending seqno_request to {}", source_peer.underlay_ip());
debug!(
"Sending seqno_request to {} for seqno {} of {}",
source_peer.underlay_ip(),
fd.seqno() + 1,
update.subnet(),
);
if let Err(e) = source_peer.send_control_packet(
SeqNoRequest::new(
fd.seqno() + 1,
@@ -648,6 +688,7 @@ impl Router {
if !update_feasible && route_entry.source().router_id() == router_id {
return;
}
inner_w.append(RouterOpLogEntry::UpdateSelectedRouteEntry(
route_key_from_update,
seqno,
+1 -1
View File
@@ -86,7 +86,7 @@ impl SourceTable {
let source_key = SourceKey::new(update.subnet(), update.router_id());
match self.get(&source_key) {
Some(entry) => {
(!update.seqno().lt(&entry.seqno()))
(update.seqno().gt(&entry.seqno()))
|| (update.seqno() == entry.seqno() && update.metric() < entry.metric())
|| update.metric().is_infinite()
}