///|
priv struct MpRoutes {
prefixes : Array[String]
path_ids : Array[UInt?]
next_hop : String?
supported : Bool
afi : Int
safi : Int
}
///|
fn read_next_hop(c : Cursor, afi : Int) -> String raise ParseError {
let length = c.u8()
if length != 4 && length != 16 && length != 32 {
raise Invalid(c.pos - 1, "不支持的单播下一跳长度")
}
if afi == 2 && length == 4 {
raise Invalid(c.pos - 1, "IPv6 下一跳长度错误")
}
let raw = c.bytes(length)
// IPv6 双地址编码保留全局地址,链路本地地址仍在原始属性中。
ip_text(if length == 32 { raw[0:16].to_owned() } else { raw })
}
///|
fn parse_mp(
value : Bytes,
reach : Bool,
addpath? : Bool = false,
) -> MpRoutes raise ParseError {
let c = Cursor::new(value)
let afi = c.u16()
let safi = c.u8()
if (afi != 1 && afi != 2) || safi != 1 {
// 不解释范围外 NLRI,但通用 MP_REACH 头及其下一跳长度不能截断。
if reach {
ignore(c.bytes(c.u8()))
ignore(c.u8())
}
return {
prefixes: [],
path_ids: [],
next_hop: None,
supported: false,
afi,
safi,
}
}
let next_hop = if reach {
let hop = read_next_hop(c, afi)
ignore(c.u8())
Some(hop)
} else {
None
}
let entries = read_nlri_paths(c, afi, addpath)
{
prefixes: entries.map(fn(entry) { entry.0 }),
path_ids: entries.map(fn(entry) { entry.1 }),
next_hop,
supported: true,
afi,
safi,
}
}
///|
fn rib_next_hop(
attributes : Attributes,
afi : Int,
) -> Attributes raise ParseError {
for attr in attributes.other {
if attr.code == 14 {
let c = Cursor::new(attr.value)
// RFC 6396 精简编码与历史采集器完整编码均可读取。
let hop = if c.remaining() > 0 && attr.value[0].to_int() != 0 {
let hop = read_next_hop(c, afi)
c.finish()
Some(hop)
} else {
parse_mp(attr.value, true).next_hop
}
return { ..attributes, next_hop: hop, }
}
}
attributes
}