From 8c1f3b2f49897e9fd9688db00baad9b09099bc0d Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 7 Jan 2025 17:24:45 -0300 Subject: [PATCH] Map IS-IS System IDs to their corresponding hostnames Signed-off-by: Renato Westphal --- src/internal_commands.rs | 51 ++++++++++++++++++++++++++++++++++++++-- src/main.rs | 2 ++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/internal_commands.rs b/src/internal_commands.rs index 35d85cf..f9666bb 100644 --- a/src/internal_commands.rs +++ b/src/internal_commands.rs @@ -4,6 +4,7 @@ // SPDX-License-Identifier: MIT // +use std::collections::BTreeMap; use std::fmt::Write; use std::process::{Child, Command, Stdio}; @@ -757,6 +758,7 @@ pub(crate) fn cmd_show_isis_adjacency( session: &mut Session, mut args: ParsedArgs, ) -> Result { + let hostnames = isis_hostnames(session)?; YangTableBuilder::new(session, DataType::All) .xpath(XPATH_PROTOCOL) .filter_list_key("type", Some(PROTOCOL_ISIS)) @@ -765,7 +767,13 @@ pub(crate) fn cmd_show_isis_adjacency( .filter_list_key("name", get_opt_arg(&mut args, "name")) .column_leaf("Interface", "name") .xpath(XPATH_ISIS_ADJACENCY) - .column_leaf("System ID", "neighbor-sysid") + .column_from_fn( + "System ID", + Box::new(move |dnode| { + let system_id = dnode.child_value("neighbor-sysid"); + hostnames.get(&system_id).cloned().unwrap_or(system_id) + }), + ) .column_leaf("SNPA", "neighbor-snpa") .column_leaf("Level", "usage") .column_leaf("State", "state") @@ -780,6 +788,7 @@ pub(crate) fn cmd_show_isis_database( session: &mut Session, _args: ParsedArgs, ) -> Result { + let hostnames = isis_hostnames(session)?; YangTableBuilder::new(session, DataType::All) .xpath(XPATH_PROTOCOL) .filter_list_key("type", Some(PROTOCOL_ISIS)) @@ -787,7 +796,17 @@ pub(crate) fn cmd_show_isis_database( .xpath(XPATH_ISIS_DATABASE) .column_leaf("Level", "level") .xpath(XPATH_ISIS_LSP) - .column_leaf("LSP ID", "lsp-id") + .column_from_fn( + "LSP ID", + Box::new(move |dnode| { + let mut lsp_id = dnode.child_value("lsp-id"); + let system_id = &lsp_id[..14]; + if let Some(hostname) = hostnames.get(system_id) { + lsp_id.replace_range(..14, hostname); + } + lsp_id + }), + ) .column_leaf_hex32("Sequence", "sequence") .column_leaf_hex16("Checksum", "checksum") .column_leaf("Lifetime", "remaining-lifetime") @@ -796,6 +815,34 @@ pub(crate) fn cmd_show_isis_database( Ok(false) } +fn isis_hostnames( + session: &mut Session, +) -> Result, String> { + let xpath = format!( + "{}[type='{}'][name='{}']/ietf-isis:isis/hostnames", + XPATH_PROTOCOL, PROTOCOL_ISIS, "main" + ); + + // Fetch hostname mappings. + let data = fetch_data(session, DataType::State, &xpath)?; + + // Collect hostname mappings into a binary tree. + let hostnames = data + .find_path(&xpath) + .unwrap() + .find_xpath("hostname") + .unwrap() + .filter_map(|dnode| { + Some(( + dnode.child_opt_value("system-id")?, + dnode.child_opt_value("hostname")?, + )) + }) + .collect(); + + Ok(hostnames) +} + // ===== OSPF "show" commands ===== const PROTOCOL_OSPFV2: &str = "ietf-ospf:ospfv2"; diff --git a/src/main.rs b/src/main.rs index 00dc9c7..71ecb48 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,8 @@ // SPDX-License-Identifier: MIT // +#![feature(let_chains)] + mod client; mod error; mod internal_commands;