Names that said the same thing twice, or two things once

- PathAttribute::UnknownPathAttribute and Capability::UnknownCapability
  are PathAttribute::Unknown and Capability::Unknown: the enum already
  says what kind of thing is unknown.
- The capability entry types are all named XxxEntry now
  (ExtendedNextHopEntry, LongLivedGracefulRestartEntry), rather than two
  of them sharing a name with the variant that holds a list of them; and
  MultiLabelCompat is MultiLabel, since nothing explained the "Compat".
- Two different things were both called Reflection: what a session needs
  to reflect routes (export.rs, still Reflection) and the identifiers a
  reflected route must not carry back to us (policy.rs, now
  ReflectorIds).
- well_known_allow's peer_is_internal is ibgp, as everywhere else.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Rayhaan JaufeerallyandClaude Fable 5.1 committed 2026-10-06 11:35:12 +02:00
1 parent 0829f873f2
commit 673920d48b
11 files changed
+68 -66

No files matched your search

+5 -5
View File
@@ -86,7 +86,7 @@ pub enum PathAttribute {
ClusterList(Vec<Ipv4Addr>), ClusterList(Vec<Ipv4Addr>),
/// An attribute this implementation does not interpret, kept as it /// An attribute this implementation does not interpret, kept as it
/// came so that it can be passed on. /// came so that it can be passed on.
UnknownPathAttribute { Unknown {
flags: PathAttributeFlags, flags: PathAttributeFlags,
type_code: u8, type_code: u8,
payload: Vec<u8>, payload: Vec<u8>,
@@ -198,7 +198,7 @@ impl PathAttribute {
Self::OnlyToCustomer(_) => ONLY_TO_CUSTOMER, Self::OnlyToCustomer(_) => ONLY_TO_CUSTOMER,
Self::OriginatorId(_) => ORIGINATOR_ID, Self::OriginatorId(_) => ORIGINATOR_ID,
Self::ClusterList(_) => CLUSTER_LIST, Self::ClusterList(_) => CLUSTER_LIST,
Self::UnknownPathAttribute { type_code, .. } => *type_code, Self::Unknown { type_code, .. } => *type_code,
} }
} }
@@ -207,7 +207,7 @@ impl PathAttribute {
fn flags(&self) -> PathAttributeFlags { fn flags(&self) -> PathAttributeFlags {
match self { match self {
// As they came: the Partial bit has to survive (RFC 4271 §5). // As they came: the Partial bit has to survive (RFC 4271 §5).
Self::UnknownPathAttribute { flags, .. } => flags.clone(), Self::Unknown { flags, .. } => flags.clone(),
known => { known => {
let (optional, transitive) = defined_flags(known.type_code()) let (optional, transitive) = defined_flags(known.type_code())
.expect("every attribute with a variant has defined flags"); .expect("every attribute with a variant has defined flags");
@@ -304,7 +304,7 @@ impl PathAttribute {
.map(|id| Ipv4Addr::from(*id)) .map(|id| Ipv4Addr::from(*id))
.collect(), .collect(),
), ),
_ => Self::UnknownPathAttribute { _ => Self::Unknown {
flags, flags,
type_code, type_code,
payload: value.to_vec(), payload: value.to_vec(),
@@ -362,7 +362,7 @@ impl PathAttribute {
out.put_slice(&id.octets()); out.put_slice(&id.octets());
} }
} }
Self::UnknownPathAttribute { payload, .. } => out.put_slice(payload), Self::Unknown { payload, .. } => out.put_slice(payload),
} }
Ok(()) Ok(())
} }
+2 -2
View File
@@ -639,7 +639,7 @@ mod tests {
test_path_attribute_roundtrip!( test_path_attribute_roundtrip!(
test_unknown_path_attribute, test_unknown_path_attribute,
&[0x80, 0x63, 0x04, 0xde, 0xad, 0xbe, 0xef], &[0x80, 0x63, 0x04, 0xde, 0xad, 0xbe, 0xef],
PathAttribute::UnknownPathAttribute { PathAttribute::Unknown {
flags: PathAttributeFlags::new( flags: PathAttributeFlags::new(
/*optional=*/ true, /*transitive=*/ false, /*partial=*/ false, /*optional=*/ true, /*transitive=*/ false, /*partial=*/ false,
/*extended_length=*/ false, /*extended_length=*/ false,
@@ -780,7 +780,7 @@ mod tests {
], ],
UpdateMessage { UpdateMessage {
withdrawn_routes: vec![], withdrawn_routes: vec![],
path_attributes: vec![PathAttribute::UnknownPathAttribute { path_attributes: vec![PathAttribute::Unknown {
flags: PathAttributeFlags::new(true, false, false, false), flags: PathAttributeFlags::new(true, false, false, false),
type_code: 0x63, type_code: 0x63,
payload: vec![0xde, 0xad, 0xbe, 0xef], payload: vec![0xde, 0xad, 0xbe, 0xef],
+27 -27
View File
@@ -237,7 +237,7 @@ pub enum Capability {
OutboundRouteFilter(Vec<OrfFamily>), OutboundRouteFilter(Vec<OrfFamily>),
/// Extended Next Hop encoding (RFC 8950). /// Extended Next Hop encoding (RFC 8950).
ExtendedNextHop { ExtendedNextHop {
entries: Vec<ExtendedNextHop>, entries: Vec<ExtendedNextHopEntry>,
}, },
/// Extended Message (RFC 8654). /// Extended Message (RFC 8654).
ExtendedMessage, ExtendedMessage,
@@ -248,7 +248,7 @@ pub enum Capability {
}, },
/// Multiple labels (RFC 8277 §2.1): for each address family, how many /// Multiple labels (RFC 8277 §2.1): for each address family, how many
/// labels the speaker can handle in one NLRI. /// labels the speaker can handle in one NLRI.
MultiLabelCompat { MultiLabel {
entries: Vec<MultiLabelEntry>, entries: Vec<MultiLabelEntry>,
}, },
BgpRole { BgpRole {
@@ -280,10 +280,10 @@ pub enum Capability {
/// Enhanced Route Refresh (RFC 7313). /// Enhanced Route Refresh (RFC 7313).
EnhancedRouteRefresh, EnhancedRouteRefresh,
/// Long Lived Graceful Restart (RFC 9494). /// Long Lived Graceful Restart (RFC 9494).
LongLivedGracefulRestart(Vec<LongLivedGracefulRestart>), LongLivedGracefulRestart(Vec<LongLivedGracefulRestartEntry>),
/// A capability this implementation has no definition for, kept as it /// A capability this implementation has no definition for, kept as it
/// came (RFC 5492 §3: what is not understood is ignored). /// came (RFC 5492 §3: what is not understood is ignored).
UnknownCapability { Unknown {
type_code: u8, type_code: u8,
value: Vec<u8>, value: Vec<u8>,
}, },
@@ -308,14 +308,14 @@ impl Capability {
Self::ExtendedNextHop { .. } => EXTENDED_NEXT_HOP, Self::ExtendedNextHop { .. } => EXTENDED_NEXT_HOP,
Self::ExtendedMessage => EXTENDED_MESSAGE, Self::ExtendedMessage => EXTENDED_MESSAGE,
Self::BgpSec { .. } => BGP_SEC, Self::BgpSec { .. } => BGP_SEC,
Self::MultiLabelCompat { .. } => MULTI_LABEL, Self::MultiLabel { .. } => MULTI_LABEL,
Self::BgpRole { .. } => BGP_ROLE, Self::BgpRole { .. } => BGP_ROLE,
Self::GracefulRestart { .. } => GRACEFUL_RESTART, Self::GracefulRestart { .. } => GRACEFUL_RESTART,
Self::FourByteAsn { .. } => FOUR_BYTE_ASN, Self::FourByteAsn { .. } => FOUR_BYTE_ASN,
Self::AddPath { .. } => ADD_PATH, Self::AddPath { .. } => ADD_PATH,
Self::EnhancedRouteRefresh => ENHANCED_ROUTE_REFRESH, Self::EnhancedRouteRefresh => ENHANCED_ROUTE_REFRESH,
Self::LongLivedGracefulRestart(_) => LONG_LIVED_GRACEFUL_RESTART, Self::LongLivedGracefulRestart(_) => LONG_LIVED_GRACEFUL_RESTART,
Self::UnknownCapability { type_code, .. } => *type_code, Self::Unknown { type_code, .. } => *type_code,
} }
} }
@@ -366,7 +366,7 @@ impl Capability {
.map_err(|_| malformed(format!("SAFI {safi} does not fit in one octet")))?; .map_err(|_| malformed(format!("SAFI {safi} does not fit in one octet")))?;
Ok(( Ok((
buf, buf,
ExtendedNextHop { ExtendedNextHopEntry {
afi: Afi(afi), afi: Afi(afi),
safi, safi,
nh_afi: Afi(nh_afi), nh_afi: Afi(nh_afi),
@@ -399,7 +399,7 @@ impl Capability {
if entries.is_empty() { if entries.is_empty() {
return Err(malformed("Multiple Labels capability with no entries")); return Err(malformed("Multiple Labels capability with no entries"));
} }
(rest, Self::MultiLabelCompat { entries }) (rest, Self::MultiLabel { entries })
} }
BGP_ROLE => { BGP_ROLE => {
let (rest, role) = be_u8(value)?; let (rest, role) = be_u8(value)?;
@@ -466,7 +466,7 @@ impl Capability {
let (buf, stale_time) = be_u24(buf)?; let (buf, stale_time) = be_u24(buf)?;
Ok(( Ok((
buf, buf,
LongLivedGracefulRestart { LongLivedGracefulRestartEntry {
afi, afi,
safi, safi,
flags, flags,
@@ -478,7 +478,7 @@ impl Capability {
} }
type_code => ( type_code => (
&[][..], &[][..],
Self::UnknownCapability { Self::Unknown {
type_code, type_code,
value: value.to_vec(), value: value.to_vec(),
}, },
@@ -524,7 +524,7 @@ impl Capability {
out.put_u8(header.0); out.put_u8(header.0);
out.put_u16(afi.0); out.put_u16(afi.0);
} }
Capability::MultiLabelCompat { entries } => { Capability::MultiLabel { entries } => {
for entry in entries { for entry in entries {
put_afi_safi(AfiSafi::new(entry.afi, entry.safi), out); put_afi_safi(AfiSafi::new(entry.afi, entry.safi), out);
out.put_u8(entry.count); out.put_u8(entry.count);
@@ -566,7 +566,7 @@ impl Capability {
out.put_slice(&entry.stale_time.to_be_bytes()[1..]); out.put_slice(&entry.stale_time.to_be_bytes()[1..]);
} }
} }
Capability::UnknownCapability { value, .. } => out.put_slice(value), Capability::Unknown { value, .. } => out.put_slice(value),
} }
Ok(()) Ok(())
} }
@@ -692,11 +692,11 @@ impl AddPathEntry {
} }
} }
/// `ExtendedNextHop` allows for the nexthop to be for a different address family /// `ExtendedNextHopEntry` allows for the nexthop to be for a different address family
/// than the one being used to advertise prefixes for. E.g. it allows for sending /// than the one being used to advertise prefixes for. E.g. it allows for sending
/// IPv4 prefixes with an IPv6 nexthop. /// IPv4 prefixes with an IPv6 nexthop.
#[derive(Debug, Clone, Serialize, PartialEq, Eq)] #[derive(Debug, Clone, Serialize, PartialEq, Eq)]
pub struct ExtendedNextHop { pub struct ExtendedNextHopEntry {
/// The Address Family to update the nexthop format for. /// The Address Family to update the nexthop format for.
pub afi: Afi, pub afi: Afi,
/// The Subsequent Address Family to update the nexthop format for. /// The Subsequent Address Family to update the nexthop format for.
@@ -743,7 +743,7 @@ impl From<&BgpRole> for u8 {
} }
#[derive(Debug, Clone, Serialize, PartialEq, Eq)] #[derive(Debug, Clone, Serialize, PartialEq, Eq)]
pub struct LongLivedGracefulRestart { pub struct LongLivedGracefulRestartEntry {
pub afi: Afi, pub afi: Afi,
pub safi: Safi, pub safi: Safi,
pub flags: u8, pub flags: u8,
@@ -780,7 +780,7 @@ mod tests {
use eyre::Result; use eyre::Result;
use crate::open::{ use crate::open::{
AddPathEntry, AddPathSendRecv, Capability, ExtendedNextHop, GracefulRestartEntry, AddPathEntry, AddPathSendRecv, Capability, ExtendedNextHopEntry, GracefulRestartEntry,
MultiLabelEntry, OpenMessage, OpenOption, OrfFamily, OrfSendRecv, OrfType, MultiLabelEntry, OpenMessage, OpenOption, OrfFamily, OrfSendRecv, OrfType,
OutboundRouteFilterEntry, OutboundRouteFilterEntry,
}; };
@@ -816,7 +816,7 @@ mod tests {
test_capability_roundtrip!( test_capability_roundtrip!(
test_route_refresh_cisco_unsupported, test_route_refresh_cisco_unsupported,
&[0x80, 0x00], &[0x80, 0x00],
Capability::UnknownCapability { Capability::Unknown {
type_code: 0x80, type_code: 0x80,
value: vec![] value: vec![]
} }
@@ -868,17 +868,17 @@ mod tests {
], ],
Capability::ExtendedNextHop { Capability::ExtendedNextHop {
entries: vec![ entries: vec![
ExtendedNextHop { ExtendedNextHopEntry {
afi: Afi::IPV4, afi: Afi::IPV4,
safi: Safi::UNICAST, safi: Safi::UNICAST,
nh_afi: Afi::IPV6, nh_afi: Afi::IPV6,
}, },
ExtendedNextHop { ExtendedNextHopEntry {
afi: Afi::IPV4, afi: Afi::IPV4,
safi: Safi::MULTICAST, safi: Safi::MULTICAST,
nh_afi: Afi::IPV6, nh_afi: Afi::IPV6,
}, },
ExtendedNextHop { ExtendedNextHopEntry {
afi: Afi::IPV4, afi: Afi::IPV4,
safi: Safi::MPLS_VPN, safi: Safi::MPLS_VPN,
nh_afi: Afi::IPV6 nh_afi: Afi::IPV6
@@ -906,7 +906,7 @@ mod tests {
afi: Afi::IPV4, afi: Afi::IPV4,
safi: Safi::UNICAST, safi: Safi::UNICAST,
}]), }]),
OpenOption::Capabilities(vec![Capability::UnknownCapability { OpenOption::Capabilities(vec![Capability::Unknown {
type_code: 0x80, type_code: 0x80,
value: vec![], value: vec![],
}]), }]),
@@ -924,17 +924,17 @@ mod tests {
}]), }]),
OpenOption::Capabilities(vec![Capability::ExtendedNextHop { OpenOption::Capabilities(vec![Capability::ExtendedNextHop {
entries: vec![ entries: vec![
ExtendedNextHop { ExtendedNextHopEntry {
afi: Afi::IPV4, afi: Afi::IPV4,
safi: Safi::UNICAST, safi: Safi::UNICAST,
nh_afi: Afi::IPV6, nh_afi: Afi::IPV6,
}, },
ExtendedNextHop { ExtendedNextHopEntry {
afi: Afi::IPV4, afi: Afi::IPV4,
safi: Safi::MULTICAST, safi: Safi::MULTICAST,
nh_afi: Afi::IPV6, nh_afi: Afi::IPV6,
}, },
ExtendedNextHop { ExtendedNextHopEntry {
afi: Afi::IPV4, afi: Afi::IPV4,
safi: Safi::MPLS_VPN, safi: Safi::MPLS_VPN,
nh_afi: Afi::IPV6, nh_afi: Afi::IPV6,
@@ -962,7 +962,7 @@ mod tests {
assert!(rest.is_empty()); assert!(rest.is_empty());
assert_eq!( assert_eq!(
cap, cap,
Capability::MultiLabelCompat { Capability::MultiLabel {
entries: vec![ entries: vec![
MultiLabelEntry { MultiLabelEntry {
afi: Afi::IPV4, afi: Afi::IPV4,
@@ -1136,7 +1136,7 @@ mod tests {
#[test] #[test]
fn long_optional_parameters_use_two_octet_lengths() { fn long_optional_parameters_use_two_octet_lengths() {
let capabilities: Vec<Capability> = (0..60) let capabilities: Vec<Capability> = (0..60)
.map(|i| Capability::UnknownCapability { .map(|i| Capability::Unknown {
type_code: 200, type_code: 200,
value: vec![i; 4], value: vec![i; 4],
}) })
@@ -1194,7 +1194,7 @@ mod tests {
/// used to be written with the length wrapped around. /// used to be written with the length wrapped around.
#[test] #[test]
fn a_capability_too_long_for_its_length_octet_is_refused() { fn a_capability_too_long_for_its_length_octet_is_refused() {
let entry = ExtendedNextHop { let entry = ExtendedNextHopEntry {
afi: Afi::IPV4, afi: Afi::IPV4,
safi: Safi::UNICAST, safi: Safi::UNICAST,
nh_afi: Afi::IPV6, nh_afi: Afi::IPV6,
+3 -3
View File
@@ -421,7 +421,7 @@ impl<'a> AttributeReader<'a> {
/// The attribute kept as bytes. /// The attribute kept as bytes.
fn opaque(raw: &RawAttribute<'_>) -> PathAttribute { fn opaque(raw: &RawAttribute<'_>) -> PathAttribute {
PathAttribute::UnknownPathAttribute { PathAttribute::Unknown {
flags: raw.flags.clone(), flags: raw.flags.clone(),
type_code: raw.type_code, type_code: raw.type_code,
payload: raw.value.to_vec(), payload: raw.value.to_vec(),
@@ -1000,7 +1000,7 @@ mod tests {
assert!(decoded.errors.is_empty()); assert!(decoded.errors.is_empty());
assert_eq!( assert_eq!(
decoded.update.path_attributes.last(), decoded.update.path_attributes.last(),
Some(&PathAttribute::UnknownPathAttribute { Some(&PathAttribute::Unknown {
flags: PathAttributeFlags(OPTIONAL_TRANSITIVE), flags: PathAttributeFlags(OPTIONAL_TRANSITIVE),
type_code: AS4_AGGREGATOR, type_code: AS4_AGGREGATOR,
payload: value.to_vec(), payload: value.to_vec(),
@@ -1204,7 +1204,7 @@ mod tests {
assert!(decoded.errors.is_empty()); assert!(decoded.errors.is_empty());
assert_eq!( assert_eq!(
decoded.update.path_attributes[3], decoded.update.path_attributes[3],
PathAttribute::UnknownPathAttribute { PathAttribute::Unknown {
flags: PathAttributeFlags(0xe0), flags: PathAttributeFlags(0xe0),
type_code: 99, type_code: 99,
payload: vec![1, 2, 3], payload: vec![1, 2, 3],
+14 -12
View File
@@ -25,8 +25,8 @@ use bgp_packet::message::{
PathAttributeFlags, RouteRefreshMessage, UpdateMessage, PathAttributeFlags, RouteRefreshMessage, UpdateMessage,
}; };
use bgp_packet::open::{ use bgp_packet::open::{
AddPathEntry, AddPathSendRecv, BgpRole, BgpSecHeader, Capability, ExtendedNextHop, AddPathEntry, AddPathSendRecv, BgpRole, BgpSecHeader, Capability, ExtendedNextHopEntry,
GracefulRestartEntry, LongLivedGracefulRestart, MultiLabelEntry, OpenMessage, OpenOption, GracefulRestartEntry, LongLivedGracefulRestartEntry, MultiLabelEntry, OpenMessage, OpenOption,
OrfFamily, OrfSendRecv, OrfType, OutboundRouteFilterEntry, OrfFamily, OrfSendRecv, OrfType, OutboundRouteFilterEntry,
}; };
use bgp_primitives::constants::{Afi, AfiSafi, IpVersion, Safi}; use bgp_primitives::constants::{Afi, AfiSafi, IpVersion, Safi};
@@ -220,7 +220,7 @@ fn unknown_attributes() -> impl Strategy<Value = Vec<PathAttribute>> {
if payload.len() > 255 { if payload.len() > 255 {
flags |= 0x10; flags |= 0x10;
} }
PathAttribute::UnknownPathAttribute { PathAttribute::Unknown {
flags: PathAttributeFlags(flags), flags: PathAttributeFlags(flags),
type_code, type_code,
payload, payload,
@@ -402,7 +402,7 @@ fn capability() -> impl Strategy<Value = Capability> {
vec((afi(), safi(), afi()), 1..4).prop_map(|entries| Capability::ExtendedNextHop { vec((afi(), safi(), afi()), 1..4).prop_map(|entries| Capability::ExtendedNextHop {
entries: entries entries: entries
.into_iter() .into_iter()
.map(|(afi, safi, nh_afi)| ExtendedNextHop { afi, safi, nh_afi }) .map(|(afi, safi, nh_afi)| ExtendedNextHopEntry { afi, safi, nh_afi })
.collect(), .collect(),
}), }),
Just(Capability::ExtendedMessage), Just(Capability::ExtendedMessage),
@@ -411,7 +411,7 @@ fn capability() -> impl Strategy<Value = Capability> {
afi, afi,
}), }),
vec((afi(), safi(), any::<u8>()), 1..4).prop_map(|entries| { vec((afi(), safi(), any::<u8>()), 1..4).prop_map(|entries| {
Capability::MultiLabelCompat { Capability::MultiLabel {
entries: entries entries: entries
.into_iter() .into_iter()
.map(|(afi, safi, count)| MultiLabelEntry { afi, safi, count }) .map(|(afi, safi, count)| MultiLabelEntry { afi, safi, count })
@@ -458,12 +458,14 @@ fn capability() -> impl Strategy<Value = Capability> {
Capability::LongLivedGracefulRestart( Capability::LongLivedGracefulRestart(
entries entries
.into_iter() .into_iter()
.map(|(afi, safi, flags, stale_time)| LongLivedGracefulRestart { .map(
afi, |(afi, safi, flags, stale_time)| LongLivedGracefulRestartEntry {
safi, afi,
flags, safi,
stale_time, flags,
}) stale_time,
},
)
.collect(), .collect(),
) )
}), }),
@@ -473,7 +475,7 @@ fn capability() -> impl Strategy<Value = Capability> {
}), }),
vec(any::<u8>(), 0..20) vec(any::<u8>(), 0..20)
) )
.prop_map(|(type_code, value)| Capability::UnknownCapability { type_code, value }), .prop_map(|(type_code, value)| Capability::Unknown { type_code, value }),
] ]
} }
+3 -3
View File
@@ -17,7 +17,7 @@ use crate::error::{ConfigError, ExportProblem, ImportProblem, OriginateProblem,
use crate::family::FamilySet; use crate::family::FamilySet;
use crate::marks::{Control, Marks, Patterns, Scrub}; use crate::marks::{Control, Marks, Patterns, Scrub};
use crate::policy::{ use crate::policy::{
ExportLimits, ExportPolicy, ImportPolicy, ImportRule, PeerRole, PrefixSet, Reflection, ExportLimits, ExportPolicy, ImportPolicy, ImportRule, PeerRole, PrefixSet, ReflectorIds,
}; };
use crate::proto::config::{self as proto, BgpConfig, OriginatedRoute, Peer}; use crate::proto::config::{self as proto, BgpConfig, OriginatedRoute, Peer};
use crate::restart::GracefulRestartConfig; use crate::restart::GracefulRestartConfig;
@@ -341,7 +341,7 @@ impl Ours {
for peer in peers { for peer in peers {
if peer.remote_asn == self.local_asn { if peer.remote_asn == self.local_asn {
peer.import.originated = Arc::clone(&originated); peer.import.originated = Arc::clone(&originated);
peer.import.reflection = Some(Reflection { peer.import.reflection = Some(ReflectorIds {
router_id: self.router_id, router_id: self.router_id,
cluster_id: self.cluster_id, cluster_id: self.cluster_id,
}); });
@@ -836,7 +836,7 @@ mod tests {
assert!(config.peers[0].reflector_client); assert!(config.peers[0].reflector_client);
assert_eq!( assert_eq!(
config.peers[0].import.reflection, config.peers[0].import.reflection,
Some(Reflection { Some(ReflectorIds {
router_id: config.router_id, router_id: config.router_id,
cluster_id: config.router_id cluster_id: config.router_id
}) })
+4 -4
View File
@@ -260,7 +260,7 @@ impl Egress<'_> {
// What we do not understand goes on if it says it may, marked // What we do not understand goes on if it says it may, marked
// as having passed a router that did not look at it; and no // as having passed a router that did not look at it; and no
// further if not (RFC 4271 §5). // further if not (RFC 4271 §5).
PathAttribute::UnknownPathAttribute { flags, .. } => { PathAttribute::Unknown { flags, .. } => {
let passes = flags.optional() && flags.transitive(); let passes = flags.optional() && flags.transitive();
if passes { if passes {
flags.set_partial(true); flags.set_partial(true);
@@ -619,12 +619,12 @@ mod tests {
communities(&[(3356, 3)]), communities(&[(3356, 3)]),
// Understood by nobody here: one that may go on, one that may // Understood by nobody here: one that may go on, one that may
// not. // not.
PathAttribute::UnknownPathAttribute { PathAttribute::Unknown {
flags: PathAttributeFlags::new(true, true, false, false), flags: PathAttributeFlags::new(true, true, false, false),
type_code: 200, type_code: 200,
payload: vec![1], payload: vec![1],
}, },
PathAttribute::UnknownPathAttribute { PathAttribute::Unknown {
flags: PathAttributeFlags::new(true, false, false, false), flags: PathAttributeFlags::new(true, false, false, false),
type_code: 201, type_code: 201,
payload: vec![2], payload: vec![2],
@@ -641,7 +641,7 @@ mod tests {
PathAttribute::Origin(OriginPathAttribute::IGP), PathAttribute::Origin(OriginPathAttribute::IGP),
AsPathAttribute::from_asns(vec![LOCAL, 3356, 64700]), AsPathAttribute::from_asns(vec![LOCAL, 3356, 64700]),
communities(&[(3356, 3)]), communities(&[(3356, 3)]),
PathAttribute::UnknownPathAttribute { PathAttribute::Unknown {
// Marked as having passed a router that did not know it. // Marked as having passed a router that did not know it.
flags: PathAttributeFlags::new(true, true, true, false), flags: PathAttributeFlags::new(true, true, true, false),
type_code: 200, type_code: 200,
+3 -3
View File
@@ -17,7 +17,7 @@ use std::time::Duration;
use bgp_packet::errors::{BgpError, CeaseSubcode, DecodeError, OpenMsgSubcode}; use bgp_packet::errors::{BgpError, CeaseSubcode, DecodeError, OpenMsgSubcode};
use bgp_packet::message::{AS_TRANS, BGP4_VERSION, Message, NotificationMessage, UpdateMessage}; use bgp_packet::message::{AS_TRANS, BGP4_VERSION, Message, NotificationMessage, UpdateMessage};
use bgp_packet::open::{ use bgp_packet::open::{
AddPathEntry, AddPathSendRecv, Capability, ExtendedNextHop, OpenMessage, OpenOption, AddPathEntry, AddPathSendRecv, Capability, ExtendedNextHopEntry, OpenMessage, OpenOption,
}; };
use bgp_primitives::constants::{Afi, AfiSafi, Safi}; use bgp_primitives::constants::{Afi, AfiSafi, Safi};
@@ -555,7 +555,7 @@ impl Fsm {
/// IPv4 unicast routes with next hops that are IPv6 addresses, as the /// IPv4 unicast routes with next hops that are IPv6 addresses, as the
/// Extended Next Hop capability names it (RFC 8950 §3). /// Extended Next Hop capability names it (RFC 8950 §3).
const IPV4_WITH_IPV6_NEXT_HOP: ExtendedNextHop = ExtendedNextHop { const IPV4_WITH_IPV6_NEXT_HOP: ExtendedNextHopEntry = ExtendedNextHopEntry {
afi: Afi::IPV4, afi: Afi::IPV4,
safi: Safi::UNICAST, safi: Safi::UNICAST,
nh_afi: Afi::IPV6, nh_afi: Afi::IPV6,
@@ -1066,7 +1066,7 @@ mod tests {
// Offered for something else: IPv6 routes with IPv4 next hops, // Offered for something else: IPv6 routes with IPv4 next hops,
// say. // say.
let other = Capability::ExtendedNextHop { let other = Capability::ExtendedNextHop {
entries: vec![ExtendedNextHop { entries: vec![ExtendedNextHopEntry {
afi: Afi::IPV6, afi: Afi::IPV6,
safi: Safi::UNICAST, safi: Safi::UNICAST,
nh_afi: Afi::IPV4, nh_afi: Afi::IPV4,
+2 -2
View File
@@ -295,10 +295,10 @@ const NO_EXPORT_SUBCONFED: (u16, u16) = (0xFFFF, 0xFF03);
/// all, as far as the well-known ones say: NO_ADVERTISE keeps it from /// all, as far as the well-known ones say: NO_ADVERTISE keeps it from
/// everyone, NO_EXPORT from other networks. (There are no confederations /// everyone, NO_EXPORT from other networks. (There are no confederations
/// here, so NO_EXPORT_SUBCONFED is the same as NO_EXPORT.) /// here, so NO_EXPORT_SUBCONFED is the same as NO_EXPORT.)
pub fn well_known_allow(communities: &[(u16, u16)], peer_is_internal: bool) -> bool { pub fn well_known_allow(communities: &[(u16, u16)], ibgp: bool) -> bool {
!communities.iter().any(|community| { !communities.iter().any(|community| {
*community == NO_ADVERTISE *community == NO_ADVERTISE
|| (!peer_is_internal && matches!(*community, NO_EXPORT | NO_EXPORT_SUBCONFED)) || (!ibgp && matches!(*community, NO_EXPORT | NO_EXPORT_SUBCONFED))
}) })
} }
+3 -3
View File
@@ -123,7 +123,7 @@ pub struct ImportPolicy {
/// For a peer in our own AS, what a route passed on inside the AS /// For a peer in our own AS, what a route passed on inside the AS
/// must not say it has already been through (RFC 4456 §8); `None` for /// must not say it has already been through (RFC 4456 §8); `None` for
/// a peer in another AS, whose routes carry no such thing. /// a peer in another AS, whose routes carry no such thing.
pub reflection: Option<Reflection>, pub reflection: Option<ReflectorIds>,
} }
/// Who we are to routes passed on from one router of our AS to another: /// Who we are to routes passed on from one router of our AS to another:
@@ -131,7 +131,7 @@ pub struct ImportPolicy {
/// whose CLUSTER_LIST holds our cluster ID has been passed on by us /// whose CLUSTER_LIST holds our cluster ID has been passed on by us
/// already. Either has gone round in a circle, and is not taken. /// already. Either has gone round in a circle, and is not taken.
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Reflection { pub struct ReflectorIds {
pub router_id: Ipv4Addr, pub router_id: Ipv4Addr,
pub cluster_id: Ipv4Addr, pub cluster_id: Ipv4Addr,
} }
@@ -1068,7 +1068,7 @@ mod tests {
let us = Ipv4Addr::new(10, 0, 0, 1); let us = Ipv4Addr::new(10, 0, 0, 1);
let cluster = Ipv4Addr::new(10, 0, 0, 9); let cluster = Ipv4Addr::new(10, 0, 0, 9);
let policy = ImportPolicy { let policy = ImportPolicy {
reflection: Some(Reflection { reflection: Some(ReflectorIds {
router_id: us, router_id: us,
cluster_id: cluster, cluster_id: cluster,
}), }),
+2 -2
View File
@@ -390,7 +390,7 @@ fn other_attribute(attribute: &PathAttribute) -> Option<OtherAttribute> {
"cluster list", "cluster list",
list(ids.iter().map(Ipv4Addr::to_string).collect(), " "), list(ids.iter().map(Ipv4Addr::to_string).collect(), " "),
), ),
PathAttribute::UnknownPathAttribute { PathAttribute::Unknown {
flags, flags,
type_code, type_code,
payload, payload,
@@ -1412,7 +1412,7 @@ mod tests {
Ipv4Addr::new(10, 0, 0, 1), Ipv4Addr::new(10, 0, 0, 1),
Ipv4Addr::new(10, 0, 0, 2), Ipv4Addr::new(10, 0, 0, 2),
]), ]),
PathAttribute::UnknownPathAttribute { PathAttribute::Unknown {
flags: PathAttributeFlags::new(true, true, false, false), flags: PathAttributeFlags::new(true, true, false, false),
type_code: 99, type_code: 99,
payload: vec![0xab, 0x01], payload: vec![0xab, 0x01],