From 6ddbbc4b002b2f337dd3e98976511c84d5dc39ed Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 30 Apr 2024 15:27:49 -0300 Subject: [PATCH] bgp: implement YANG notifications Implement the "established" and "backward-transition" notifications defined in the IETF BGP model. The topology tests data have been update accordingly. Signed-off-by: Renato Westphal --- holo-bgp/src/neighbor.rs | 8 ++ holo-bgp/src/northbound/mod.rs | 1 + holo-bgp/src/northbound/notification.rs | 77 +++++++++++++++++++ .../topo1-1/rt1/output/northbound-notif.jsonl | 2 + .../topo1-1/rt2/output/northbound-notif.jsonl | 2 + .../topo1-1/rt3/output/northbound-notif.jsonl | 2 + .../topo1-1/rt4/output/northbound-notif.jsonl | 2 + .../topo2-1/rt1/output/northbound-notif.jsonl | 3 + .../topo2-1/rt2/output/northbound-notif.jsonl | 2 + .../topo2-1/rt3/output/northbound-notif.jsonl | 2 + .../topo2-1/rt4/output/northbound-notif.jsonl | 2 + .../topo2-1/rt5/output/northbound-notif.jsonl | 2 + .../topo2-1/rt6/output/northbound-notif.jsonl | 3 + .../deviations/ietf-bgp-holo-deviations.yang | 36 +++++++++ 14 files changed, 144 insertions(+) create mode 100644 holo-bgp/src/northbound/notification.rs create mode 100644 holo-bgp/tests/conformance/topologies/topo1-1/rt1/output/northbound-notif.jsonl create mode 100644 holo-bgp/tests/conformance/topologies/topo1-1/rt2/output/northbound-notif.jsonl create mode 100644 holo-bgp/tests/conformance/topologies/topo1-1/rt3/output/northbound-notif.jsonl create mode 100644 holo-bgp/tests/conformance/topologies/topo1-1/rt4/output/northbound-notif.jsonl create mode 100644 holo-bgp/tests/conformance/topologies/topo2-1/rt1/output/northbound-notif.jsonl create mode 100644 holo-bgp/tests/conformance/topologies/topo2-1/rt2/output/northbound-notif.jsonl create mode 100644 holo-bgp/tests/conformance/topologies/topo2-1/rt3/output/northbound-notif.jsonl create mode 100644 holo-bgp/tests/conformance/topologies/topo2-1/rt4/output/northbound-notif.jsonl create mode 100644 holo-bgp/tests/conformance/topologies/topo2-1/rt5/output/northbound-notif.jsonl create mode 100644 holo-bgp/tests/conformance/topologies/topo2-1/rt6/output/northbound-notif.jsonl diff --git a/holo-bgp/src/neighbor.rs b/holo-bgp/src/neighbor.rs index 99df858b..de165119 100644 --- a/holo-bgp/src/neighbor.rs +++ b/holo-bgp/src/neighbor.rs @@ -25,6 +25,7 @@ use crate::debug::Debug; use crate::error::Error; use crate::instance::{Instance, InstanceUpView}; use crate::northbound::configuration::{InstanceCfg, NeighborCfg}; +use crate::northbound::notification; use crate::packet::attribute::Attrs; use crate::packet::consts::{ Afi, ErrorCode, FsmErrorSubcode, Safi, AS_TRANS, BGP_VERSION, @@ -482,6 +483,13 @@ impl Neighbor { Debug::NbrFsmTransition(&self.remote_addr, &self.state, &next_state) .log(); + // Send YANG-modeled notification. + if next_state == fsm::State::Established { + notification::established(instance, self); + } else if self.state == fsm::State::Established { + notification::backward_transition(instance, self); + } + // Keep track of the time that the BGP session last transitioned in or // out of the Established state. if self.state == fsm::State::Established diff --git a/holo-bgp/src/northbound/mod.rs b/holo-bgp/src/northbound/mod.rs index 55ed05c5..a6760a6a 100644 --- a/holo-bgp/src/northbound/mod.rs +++ b/holo-bgp/src/northbound/mod.rs @@ -5,6 +5,7 @@ // pub mod configuration; +pub mod notification; pub mod rpc; pub mod state; pub mod yang; diff --git a/holo-bgp/src/northbound/notification.rs b/holo-bgp/src/northbound/notification.rs new file mode 100644 index 00000000..ebe93476 --- /dev/null +++ b/holo-bgp/src/northbound/notification.rs @@ -0,0 +1,77 @@ +// +// Copyright (c) The Holo Core Contributors +// +// SPDX-License-Identifier: MIT +// + +use holo_northbound::notification; +use holo_northbound::paths::control_plane_protocol; +use holo_northbound::paths::control_plane_protocol::bgp; +use holo_utils::protocol::Protocol; +use holo_yang::ToYang; + +use crate::instance::InstanceUpView; +use crate::neighbor::Neighbor; + +// ===== global functions ===== + +pub(crate) fn established(instance: &InstanceUpView<'_>, nbr: &Neighbor) { + use bgp::neighbors::established::{self, Established}; + + let path = format!( + "{}{}{}", + control_plane_protocol::PATH, + control_plane_protocol::list_keys( + Protocol::BGP.to_yang(), + instance.name + ), + established::RELATIVE_PATH, + ); + let data = Established { + remote_address: Some(nbr.remote_addr.to_string().into()), + }; + notification::send(&instance.tx.nb, path, data); +} + +pub(crate) fn backward_transition( + instance: &InstanceUpView<'_>, + nbr: &Neighbor, +) { + use bgp::neighbors::backward_transition::notification_received::NotificationReceived; + use bgp::neighbors::backward_transition::notification_sent::NotificationSent; + use bgp::neighbors::backward_transition::{self, BackwardTransition}; + + let path = format!( + "{}{}{}", + control_plane_protocol::PATH, + control_plane_protocol::list_keys( + Protocol::BGP.to_yang(), + instance.name + ), + backward_transition::RELATIVE_PATH, + ); + let data = BackwardTransition { + remote_addr: Some(nbr.remote_addr.to_string().into()), + notification_received: nbr.notification_rcvd.as_ref().map( + |(time, notif)| NotificationReceived { + last_notification: Some(time.to_rfc3339().into()), + last_error: Some(notif.to_yang()), + last_error_code: Some(notif.error_code.to_string().into()), + last_error_subcode: Some( + notif.error_subcode.to_string().into(), + ), + }, + ), + notification_sent: nbr.notification_sent.as_ref().map( + |(time, notif)| NotificationSent { + last_notification: Some(time.to_rfc3339().into()), + last_error: Some(notif.to_yang()), + last_error_code: Some(notif.error_code.to_string().into()), + last_error_subcode: Some( + notif.error_subcode.to_string().into(), + ), + }, + ), + }; + notification::send(&instance.tx.nb, path, data); +} diff --git a/holo-bgp/tests/conformance/topologies/topo1-1/rt1/output/northbound-notif.jsonl b/holo-bgp/tests/conformance/topologies/topo1-1/rt1/output/northbound-notif.jsonl new file mode 100644 index 00000000..8f40578a --- /dev/null +++ b/holo-bgp/tests/conformance/topologies/topo1-1/rt1/output/northbound-notif.jsonl @@ -0,0 +1,2 @@ +{"ietf-routing:routing":{"control-plane-protocols":{"control-plane-protocol":[{"type":"ietf-bgp:bgp","name":"test","ietf-bgp:bgp":{"neighbors":{"established":{"remote-address":"10.0.1.2"}}}}]}}} +{"ietf-routing:routing":{"control-plane-protocols":{"control-plane-protocol":[{"type":"ietf-bgp:bgp","name":"test","ietf-bgp:bgp":{"neighbors":{"established":{"remote-address":"10.0.2.3"}}}}]}}} \ No newline at end of file diff --git a/holo-bgp/tests/conformance/topologies/topo1-1/rt2/output/northbound-notif.jsonl b/holo-bgp/tests/conformance/topologies/topo1-1/rt2/output/northbound-notif.jsonl new file mode 100644 index 00000000..c7770845 --- /dev/null +++ b/holo-bgp/tests/conformance/topologies/topo1-1/rt2/output/northbound-notif.jsonl @@ -0,0 +1,2 @@ +{"ietf-routing:routing":{"control-plane-protocols":{"control-plane-protocol":[{"type":"ietf-bgp:bgp","name":"test","ietf-bgp:bgp":{"neighbors":{"established":{"remote-address":"10.0.1.1"}}}}]}}} +{"ietf-routing:routing":{"control-plane-protocols":{"control-plane-protocol":[{"type":"ietf-bgp:bgp","name":"test","ietf-bgp:bgp":{"neighbors":{"established":{"remote-address":"10.0.3.4"}}}}]}}} \ No newline at end of file diff --git a/holo-bgp/tests/conformance/topologies/topo1-1/rt3/output/northbound-notif.jsonl b/holo-bgp/tests/conformance/topologies/topo1-1/rt3/output/northbound-notif.jsonl new file mode 100644 index 00000000..a60d22ad --- /dev/null +++ b/holo-bgp/tests/conformance/topologies/topo1-1/rt3/output/northbound-notif.jsonl @@ -0,0 +1,2 @@ +{"ietf-routing:routing":{"control-plane-protocols":{"control-plane-protocol":[{"type":"ietf-bgp:bgp","name":"test","ietf-bgp:bgp":{"neighbors":{"established":{"remote-address":"10.0.2.1"}}}}]}}} +{"ietf-routing:routing":{"control-plane-protocols":{"control-plane-protocol":[{"type":"ietf-bgp:bgp","name":"test","ietf-bgp:bgp":{"neighbors":{"established":{"remote-address":"4.4.4.4"}}}}]}}} \ No newline at end of file diff --git a/holo-bgp/tests/conformance/topologies/topo1-1/rt4/output/northbound-notif.jsonl b/holo-bgp/tests/conformance/topologies/topo1-1/rt4/output/northbound-notif.jsonl new file mode 100644 index 00000000..5c22d9c1 --- /dev/null +++ b/holo-bgp/tests/conformance/topologies/topo1-1/rt4/output/northbound-notif.jsonl @@ -0,0 +1,2 @@ +{"ietf-routing:routing":{"control-plane-protocols":{"control-plane-protocol":[{"type":"ietf-bgp:bgp","name":"test","ietf-bgp:bgp":{"neighbors":{"established":{"remote-address":"10.0.3.2"}}}}]}}} +{"ietf-routing:routing":{"control-plane-protocols":{"control-plane-protocol":[{"type":"ietf-bgp:bgp","name":"test","ietf-bgp:bgp":{"neighbors":{"established":{"remote-address":"3.3.3.3"}}}}]}}} \ No newline at end of file diff --git a/holo-bgp/tests/conformance/topologies/topo2-1/rt1/output/northbound-notif.jsonl b/holo-bgp/tests/conformance/topologies/topo2-1/rt1/output/northbound-notif.jsonl new file mode 100644 index 00000000..31d49ceb --- /dev/null +++ b/holo-bgp/tests/conformance/topologies/topo2-1/rt1/output/northbound-notif.jsonl @@ -0,0 +1,3 @@ +{"ietf-routing:routing":{"control-plane-protocols":{"control-plane-protocol":[{"type":"ietf-bgp:bgp","name":"test","ietf-bgp:bgp":{"neighbors":{"established":{"remote-address":"10.0.1.2"}}}}]}}} +{"ietf-routing:routing":{"control-plane-protocols":{"control-plane-protocol":[{"type":"ietf-bgp:bgp","name":"test","ietf-bgp:bgp":{"neighbors":{"established":{"remote-address":"10.0.2.4"}}}}]}}} +{"ietf-routing:routing":{"control-plane-protocols":{"control-plane-protocol":[{"type":"ietf-bgp:bgp","name":"test","ietf-bgp:bgp":{"neighbors":{"established":{"remote-address":"10.0.3.5"}}}}]}}} \ No newline at end of file diff --git a/holo-bgp/tests/conformance/topologies/topo2-1/rt2/output/northbound-notif.jsonl b/holo-bgp/tests/conformance/topologies/topo2-1/rt2/output/northbound-notif.jsonl new file mode 100644 index 00000000..241c0c13 --- /dev/null +++ b/holo-bgp/tests/conformance/topologies/topo2-1/rt2/output/northbound-notif.jsonl @@ -0,0 +1,2 @@ +{"ietf-routing:routing":{"control-plane-protocols":{"control-plane-protocol":[{"type":"ietf-bgp:bgp","name":"test","ietf-bgp:bgp":{"neighbors":{"established":{"remote-address":"10.0.1.1"}}}}]}}} +{"ietf-routing:routing":{"control-plane-protocols":{"control-plane-protocol":[{"type":"ietf-bgp:bgp","name":"test","ietf-bgp:bgp":{"neighbors":{"established":{"remote-address":"10.0.4.3"}}}}]}}} \ No newline at end of file diff --git a/holo-bgp/tests/conformance/topologies/topo2-1/rt3/output/northbound-notif.jsonl b/holo-bgp/tests/conformance/topologies/topo2-1/rt3/output/northbound-notif.jsonl new file mode 100644 index 00000000..082546f5 --- /dev/null +++ b/holo-bgp/tests/conformance/topologies/topo2-1/rt3/output/northbound-notif.jsonl @@ -0,0 +1,2 @@ +{"ietf-routing:routing":{"control-plane-protocols":{"control-plane-protocol":[{"type":"ietf-bgp:bgp","name":"test","ietf-bgp:bgp":{"neighbors":{"established":{"remote-address":"10.0.4.2"}}}}]}}} +{"ietf-routing:routing":{"control-plane-protocols":{"control-plane-protocol":[{"type":"ietf-bgp:bgp","name":"test","ietf-bgp:bgp":{"neighbors":{"established":{"remote-address":"10.0.5.6"}}}}]}}} \ No newline at end of file diff --git a/holo-bgp/tests/conformance/topologies/topo2-1/rt4/output/northbound-notif.jsonl b/holo-bgp/tests/conformance/topologies/topo2-1/rt4/output/northbound-notif.jsonl new file mode 100644 index 00000000..1fc76313 --- /dev/null +++ b/holo-bgp/tests/conformance/topologies/topo2-1/rt4/output/northbound-notif.jsonl @@ -0,0 +1,2 @@ +{"ietf-routing:routing":{"control-plane-protocols":{"control-plane-protocol":[{"type":"ietf-bgp:bgp","name":"test","ietf-bgp:bgp":{"neighbors":{"established":{"remote-address":"10.0.2.1"}}}}]}}} +{"ietf-routing:routing":{"control-plane-protocols":{"control-plane-protocol":[{"type":"ietf-bgp:bgp","name":"test","ietf-bgp:bgp":{"neighbors":{"established":{"remote-address":"10.0.6.6"}}}}]}}} \ No newline at end of file diff --git a/holo-bgp/tests/conformance/topologies/topo2-1/rt5/output/northbound-notif.jsonl b/holo-bgp/tests/conformance/topologies/topo2-1/rt5/output/northbound-notif.jsonl new file mode 100644 index 00000000..9e808d43 --- /dev/null +++ b/holo-bgp/tests/conformance/topologies/topo2-1/rt5/output/northbound-notif.jsonl @@ -0,0 +1,2 @@ +{"ietf-routing:routing":{"control-plane-protocols":{"control-plane-protocol":[{"type":"ietf-bgp:bgp","name":"test","ietf-bgp:bgp":{"neighbors":{"established":{"remote-address":"10.0.3.1"}}}}]}}} +{"ietf-routing:routing":{"control-plane-protocols":{"control-plane-protocol":[{"type":"ietf-bgp:bgp","name":"test","ietf-bgp:bgp":{"neighbors":{"established":{"remote-address":"10.0.7.6"}}}}]}}} \ No newline at end of file diff --git a/holo-bgp/tests/conformance/topologies/topo2-1/rt6/output/northbound-notif.jsonl b/holo-bgp/tests/conformance/topologies/topo2-1/rt6/output/northbound-notif.jsonl new file mode 100644 index 00000000..4968c245 --- /dev/null +++ b/holo-bgp/tests/conformance/topologies/topo2-1/rt6/output/northbound-notif.jsonl @@ -0,0 +1,3 @@ +{"ietf-routing:routing":{"control-plane-protocols":{"control-plane-protocol":[{"type":"ietf-bgp:bgp","name":"test","ietf-bgp:bgp":{"neighbors":{"established":{"remote-address":"10.0.7.5"}}}}]}}} +{"ietf-routing:routing":{"control-plane-protocols":{"control-plane-protocol":[{"type":"ietf-bgp:bgp","name":"test","ietf-bgp:bgp":{"neighbors":{"established":{"remote-address":"10.0.5.3"}}}}]}}} +{"ietf-routing:routing":{"control-plane-protocols":{"control-plane-protocol":[{"type":"ietf-bgp:bgp","name":"test","ietf-bgp:bgp":{"neighbors":{"established":{"remote-address":"10.0.6.4"}}}}]}}} \ No newline at end of file diff --git a/holo-yang/modules/deviations/ietf-bgp-holo-deviations.yang b/holo-yang/modules/deviations/ietf-bgp-holo-deviations.yang index 21552544..bbdafee0 100644 --- a/holo-yang/modules/deviations/ietf-bgp-holo-deviations.yang +++ b/holo-yang/modules/deviations/ietf-bgp-holo-deviations.yang @@ -876,6 +876,42 @@ module ietf-bgp-holo-deviations { } */ + /* + deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/bgp:bgp/bgp:neighbors/bgp:established" { + deviate not-supported; + } + */ + + /* + deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/bgp:bgp/bgp:neighbors/bgp:established/bgp:remote-address" { + deviate not-supported; + } + */ + + deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/bgp:bgp/bgp:neighbors/bgp:backward-transition/bgp:notification-received/bgp:last-encapsulated-error" { + deviate not-supported; + } + + deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/bgp:bgp/bgp:neighbors/bgp:backward-transition/bgp:notification-received/bgp:last-encapsulated-error-code" { + deviate not-supported; + } + + deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/bgp:bgp/bgp:neighbors/bgp:backward-transition/bgp:notification-received/bgp:last-encapsulated-error-subcode" { + deviate not-supported; + } + + deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/bgp:bgp/bgp:neighbors/bgp:backward-transition/bgp:notification-sent/bgp:last-encapsulated-error" { + deviate not-supported; + } + + deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/bgp:bgp/bgp:neighbors/bgp:backward-transition/bgp:notification-sent/bgp:last-encapsulated-error-code" { + deviate not-supported; + } + + deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/bgp:bgp/bgp:neighbors/bgp:backward-transition/bgp:notification-sent/bgp:last-encapsulated-error-subcode" { + deviate not-supported; + } + /* deviation "/rt:routing/rt:control-plane-protocols/rt:control-plane-protocol/bgp:bgp/bgp:neighbors/bgp:neighbor" { deviate not-supported;