use crate::protocols::ospf::lsa::{encode_lsa_headers, OspfLsaHeader, OSPF_LSA_HEADER_LEN};
#[derive(Debug, Clone)]
pub struct OspfLinkStateAck {
lsa_headers: Vec<OspfLsaHeader>,
}
impl OspfLinkStateAck {
pub fn new() -> Self {
Self {
lsa_headers: Vec::new(),
}
}
pub(crate) fn from_decoded_parts(lsa_headers: Vec<OspfLsaHeader>) -> Self {
Self { lsa_headers }
}
pub fn lsa_header(mut self, header: OspfLsaHeader) -> Self {
self.lsa_headers.push(header);
self
}
pub fn lsa_headers<I>(mut self, headers: I) -> Self
where
I: IntoIterator<Item = OspfLsaHeader>,
{
self.lsa_headers.extend(headers);
self
}
pub fn lsa_headers_value(&self) -> &[OspfLsaHeader] {
&self.lsa_headers
}
pub(crate) fn encoded_len(&self) -> usize {
self.lsa_headers.len() * OSPF_LSA_HEADER_LEN
}
pub(crate) fn encode(&self, out: &mut Vec<u8>) {
encode_lsa_headers(&self.lsa_headers, out);
}
}
impl Default for OspfLinkStateAck {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use core::net::Ipv4Addr;
#[test]
fn ospf_link_state_ack_body_compiles_with_two_lsa_headers() {
use crate::packet::{Layer, Packet};
use crate::protocols::ospf::lsa::{OspfLsaHeader, OSPF_LSA_NETWORK, OSPF_LSA_ROUTER};
use crate::protocols::ospf::{Ospfv2, OSPF_HEADER_LEN, OSPF_TYPE_LINK_STATE_ACK};
let ack = OspfLinkStateAck::new()
.lsa_header(
OspfLsaHeader::new()
.ls_type(OSPF_LSA_ROUTER)
.link_state_id(Ipv4Addr::new(192, 0, 2, 1))
.advertising_router(Ipv4Addr::new(192, 0, 2, 1))
.ls_sequence_number(0x8000_0001),
)
.lsa_header(
OspfLsaHeader::new()
.ls_type(OSPF_LSA_NETWORK)
.link_state_id(Ipv4Addr::new(192, 0, 2, 2))
.advertising_router(Ipv4Addr::new(198, 51, 100, 7))
.ls_sequence_number(0x8000_0002),
);
let mut body = Vec::new();
ack.encode(&mut body);
assert_eq!(ack.encoded_len(), 2 * OSPF_LSA_HEADER_LEN);
assert_eq!(body.len(), ack.encoded_len());
assert_eq!(body.len(), 40);
let mut expected_headers = Vec::new();
encode_lsa_headers(ack.lsa_headers_value(), &mut expected_headers);
assert_eq!(body, expected_headers);
assert_eq!(expected_headers.len(), 2 * OSPF_LSA_HEADER_LEN);
let ospf = Ospfv2::link_state_ack().with_link_state_ack(|a| {
*a = ack.clone();
});
let bytes = Packet::from_layer(ospf)
.compile()
.expect("LinkStateAck compiles");
let total = OSPF_HEADER_LEN + body.len();
assert_eq!(bytes.len(), total);
assert_eq!(&bytes[2..4], &(total as u16).to_be_bytes());
assert_eq!(bytes[1], OSPF_TYPE_LINK_STATE_ACK);
assert_eq!(&bytes[OSPF_HEADER_LEN..], body.as_slice());
let layer = Ospfv2::link_state_ack().with_link_state_ack(|a| *a = ack);
assert_eq!(layer.encoded_len(), total);
}
}