1pub mod serde;
8
9use std::borrow::Cow;
10use std::collections::HashMap;
11use std::sync::{Arc, LazyLock as Lazy, OnceLock};
12
13use maplit::hashmap;
14use yang3::context::{
15 Context, ContextFlags, EmbeddedModuleKey, EmbeddedModules,
16};
17use yang3::data::DataNodeRef;
18
19pub static YANG_CTX: OnceLock<Arc<Context>> = OnceLock::new();
21
22pub static YANG_EMBEDDED_MODULES: Lazy<EmbeddedModules> = Lazy::new(|| {
27 hashmap! {
28 EmbeddedModuleKey::new("ieee802-dot1q-types", Some("2022-01-19"), None, None) =>
30 include_str!("../modules/ieee/ieee802-dot1q-types@2022-01-19.yang"),
31 EmbeddedModuleKey::new("iana-bfd-types", Some("2021-10-21"), None, None) =>
33 include_str!("../modules/ietf/iana-bfd-types@2021-10-21.yang"),
34 EmbeddedModuleKey::new("iana-bgp-community-types", Some("2023-07-05"), None, None) =>
35 include_str!("../modules/ietf/iana-bgp-community-types@2023-07-05.yang"),
36 EmbeddedModuleKey::new("iana-bgp-notification", Some("2023-07-05"), None, None) =>
37 include_str!("../modules/ietf/iana-bgp-notification@2023-07-05.yang"),
38 EmbeddedModuleKey::new("iana-bgp-rib-types", Some("2023-07-05"), None, None) =>
39 include_str!("../modules/ietf/iana-bgp-rib-types@2023-07-05.yang"),
40 EmbeddedModuleKey::new("iana-bgp-types", Some("2023-07-05"), None, None) =>
41 include_str!("../modules/ietf/iana-bgp-types@2023-07-05.yang"),
42 EmbeddedModuleKey::new("iana-crypt-hash", Some("2014-08-06"), None, None) =>
43 include_str!("../modules/ietf/iana-crypt-hash@2014-08-06.yang"),
44 EmbeddedModuleKey::new("iana-if-type", Some("2017-01-19"), None, None) =>
45 include_str!("../modules/ietf/iana-if-type@2017-01-19.yang"),
46 EmbeddedModuleKey::new("iana-routing-types", Some("2018-10-29"), None, None) =>
47 include_str!("../modules/ietf/iana-routing-types@2018-10-29.yang"),
48 EmbeddedModuleKey::new("ietf-bfd-ip-mh", Some("2022-09-22"), None, None) =>
49 include_str!("../modules/ietf/ietf-bfd-ip-mh@2022-09-22.yang"),
50 EmbeddedModuleKey::new("ietf-bfd-ip-sh", Some("2022-09-22"), None, None) =>
51 include_str!("../modules/ietf/ietf-bfd-ip-sh@2022-09-22.yang"),
52 EmbeddedModuleKey::new("ietf-bfd-types", Some("2022-09-22"), None, None) =>
53 include_str!("../modules/ietf/ietf-bfd-types@2022-09-22.yang"),
54 EmbeddedModuleKey::new("ietf-bfd", Some("2022-09-22"), None, None) =>
55 include_str!("../modules/ietf/ietf-bfd@2022-09-22.yang"),
56 EmbeddedModuleKey::new("ietf-bier", Some("2023-09-16"), None, None) =>
57 include_str!("../modules/ietf/ietf-bier@2023-09-16.yang"),
58 EmbeddedModuleKey::new("ietf-bgp", Some("2023-07-05"), None, None) =>
59 include_str!("../modules/ietf/ietf-bgp@2023-07-05.yang"),
60 EmbeddedModuleKey::new("ietf-bgp", Some("2023-07-05"), Some("ietf-bgp-capabilities"), Some("2023-07-05")) =>
61 include_str!("../modules/ietf/ietf-bgp-capabilities@2023-07-05.yang"),
62 EmbeddedModuleKey::new("ietf-bgp", Some("2023-07-05"), Some("ietf-bgp-common"), Some("2023-07-05")) =>
63 include_str!("../modules/ietf/ietf-bgp-common@2023-07-05.yang"),
64 EmbeddedModuleKey::new("ietf-bgp", Some("2023-07-05"), Some("ietf-bgp-common-multiprotocol"), Some("2023-07-05")) =>
65 include_str!("../modules/ietf/ietf-bgp-common-multiprotocol@2023-07-05.yang"),
66 EmbeddedModuleKey::new("ietf-bgp", Some("2023-07-05"), Some("ietf-bgp-common-structure"), Some("2023-07-05")) =>
67 include_str!("../modules/ietf/ietf-bgp-common-structure@2023-07-05.yang"),
68 EmbeddedModuleKey::new("ietf-bgp", Some("2023-07-05"), Some("ietf-bgp-neighbor"), Some("2023-07-05")) =>
69 include_str!("../modules/ietf/ietf-bgp-neighbor@2023-07-05.yang"),
70 EmbeddedModuleKey::new("ietf-bgp", Some("2023-07-05"), Some("ietf-bgp-rib"), Some("2023-07-05")) =>
71 include_str!("../modules/ietf/ietf-bgp-rib@2023-07-05.yang"),
72 EmbeddedModuleKey::new("ietf-bgp", Some("2023-07-05"), Some("ietf-bgp-rib-attributes"), Some("2023-07-05")) =>
73 include_str!("../modules/ietf/ietf-bgp-rib-attributes@2023-07-05.yang"),
74 EmbeddedModuleKey::new("ietf-bgp", Some("2023-07-05"), Some("ietf-bgp-rib-tables"), Some("2023-07-05")) =>
75 include_str!("../modules/ietf/ietf-bgp-rib-tables@2023-07-05.yang"),
76 EmbeddedModuleKey::new("ietf-bgp-policy", Some("2023-07-05"), None, None) =>
77 include_str!("../modules/ietf/ietf-bgp-policy@2023-07-05.yang"),
78 EmbeddedModuleKey::new("ietf-if-extensions", Some("2023-01-26"), None, None) =>
79 include_str!("../modules/ietf/ietf-if-extensions@2023-01-26.yang"),
80 EmbeddedModuleKey::new("ietf-if-vlan-encapsulation", Some("2023-01-26"), None, None) =>
81 include_str!("../modules/ietf/ietf-if-vlan-encapsulation@2023-01-26.yang"),
82 EmbeddedModuleKey::new("ietf-interfaces", Some("2018-02-20"), None, None) =>
83 include_str!("../modules/ietf/ietf-interfaces@2018-02-20.yang"),
84 EmbeddedModuleKey::new("ietf-ip", Some("2018-02-22"), None, None) =>
85 include_str!("../modules/ietf/ietf-ip@2018-02-22.yang"),
86 EmbeddedModuleKey::new("ietf-ipv4-unicast-routing", Some("2018-03-13"), None, None) =>
87 include_str!("../modules/ietf/ietf-ipv4-unicast-routing@2018-03-13.yang"),
88 EmbeddedModuleKey::new("ietf-ipv6-unicast-routing", Some("2018-03-13"), None, None) =>
89 include_str!("../modules/ietf/ietf-ipv6-unicast-routing@2018-03-13.yang"),
90 EmbeddedModuleKey::new("ietf-ipv6-unicast-routing", Some("2018-03-13"), Some("ietf-ipv6-router-advertisements"), Some("2018-03-13")) =>
91 include_str!("../modules/ietf/ietf-ipv6-router-advertisements@2018-03-13.yang"),
92 EmbeddedModuleKey::new("ietf-isis", Some("2022-10-19"), None, None) =>
93 include_str!("../modules/ietf/ietf-isis@2022-10-19.yang"),
94 EmbeddedModuleKey::new("ietf-key-chain", Some("2017-06-15"), None, None) =>
95 include_str!("../modules/ietf/ietf-key-chain@2017-06-15.yang"),
96 EmbeddedModuleKey::new("ietf-mpls", Some("2020-12-18"), None, None) =>
97 include_str!("../modules/ietf/ietf-mpls@2020-12-18.yang"),
98 EmbeddedModuleKey::new("ietf-mpls-ldp", Some("2022-03-14"), None, None) =>
99 include_str!("../modules/ietf/ietf-mpls-ldp@2022-03-14.yang"),
100 EmbeddedModuleKey::new("ietf-netconf-acm", Some("2018-02-14"), None, None) =>
101 include_str!("../modules/ietf/ietf-netconf-acm@2018-02-14.yang"),
102 EmbeddedModuleKey::new("ietf-ospf", Some("2022-10-19"), None, None) =>
103 include_str!("../modules/ietf/ietf-ospf@2022-10-19.yang"),
104 EmbeddedModuleKey::new("ietf-ospf-sr-mpls", Some("2024-06-19"), None, None) =>
105 include_str!("../modules/ietf/ietf-ospf-sr-mpls@2024-06-19.yang"),
106 EmbeddedModuleKey::new("ietf-ospfv3-extended-lsa", Some("2024-06-07"), None, None) =>
107 include_str!("../modules/ietf/ietf-ospfv3-extended-lsa@2024-06-07.yang"),
108 EmbeddedModuleKey::new("ietf-rip", Some("2020-02-20"), None, None) =>
109 include_str!("../modules/ietf/ietf-rip@2020-02-20.yang"),
110 EmbeddedModuleKey::new("ietf-system", Some("2014-08-06"), None, None) =>
111 include_str!("../modules/ietf/ietf-system@2014-08-06.yang"),
112 EmbeddedModuleKey::new("ietf-routing", Some("2018-03-13"), None, None) =>
113 include_str!("../modules/ietf/ietf-routing@2018-03-13.yang"),
114 EmbeddedModuleKey::new("ietf-routing-policy", Some("2021-10-11"), None, None) =>
115 include_str!("../modules/ietf/ietf-routing-policy@2021-10-11.yang"),
116 EmbeddedModuleKey::new("ietf-routing-types", Some("2017-12-04"), None, None) =>
117 include_str!("../modules/ietf/ietf-routing-types@2017-12-04.yang"),
118 EmbeddedModuleKey::new("ietf-segment-routing-common", Some("2021-05-26"), None, None) =>
119 include_str!("../modules/ietf/ietf-segment-routing-common@2021-05-26.yang"),
120 EmbeddedModuleKey::new("ietf-segment-routing-mpls", Some("2021-05-26"), None, None) =>
121 include_str!("../modules/ietf/ietf-segment-routing-mpls@2021-05-26.yang"),
122 EmbeddedModuleKey::new("ietf-segment-routing", Some("2021-05-26"), None, None) =>
123 include_str!("../modules/ietf/ietf-segment-routing@2021-05-26.yang"),
124 EmbeddedModuleKey::new("ietf-tcp", Some("2022-09-11"), None, None) =>
125 include_str!("../modules/ietf/ietf-tcp@2022-09-11.yang"),
126 EmbeddedModuleKey::new("ietf-tcp-common", Some("2023-04-17"), None, None) =>
127 include_str!("../modules/ietf/ietf-tcp-common@2023-04-17.yang"),
128 EmbeddedModuleKey::new("holo-bgp", None, None, None) =>
130 include_str!("../modules/augmentations/holo-bgp.yang"),
131 EmbeddedModuleKey::new("holo-ospf", None, None, None) =>
132 include_str!("../modules/augmentations/holo-ospf.yang"),
133 EmbeddedModuleKey::new("holo-ospf-dev", None, None, None) =>
134 include_str!("../modules/augmentations/holo-ospf-dev.yang"),
135 EmbeddedModuleKey::new("holo-routing", None, None, None) =>
136 include_str!("../modules/augmentations/holo-routing.yang"),
137 EmbeddedModuleKey::new("holo-ietf-bgp-deviations", None, None, None) =>
139 include_str!("../modules/deviations/holo-ietf-bgp-deviations.yang"),
140 EmbeddedModuleKey::new("holo-ietf-bier-deviations", None, None, None) =>
141 include_str!("../modules/deviations/holo-ietf-bier-deviations.yang"),
142 EmbeddedModuleKey::new("holo-ietf-mpls-ldp-deviations", None, None, None) =>
143 include_str!("../modules/deviations/holo-ietf-mpls-ldp-deviations.yang"),
144 EmbeddedModuleKey::new("holo-ietf-if-extensions-deviations", None, None, None) =>
145 include_str!("../modules/deviations/holo-ietf-if-extensions-deviations.yang"),
146 EmbeddedModuleKey::new("holo-ietf-if-vlan-encapsulation-deviations", None, None, None) =>
147 include_str!("../modules/deviations/holo-ietf-if-vlan-encapsulation-deviations.yang"),
148 EmbeddedModuleKey::new("holo-ietf-interfaces-deviations", None, None, None) =>
149 include_str!("../modules/deviations/holo-ietf-interfaces-deviations.yang"),
150 EmbeddedModuleKey::new("holo-ietf-ip-deviations", None, None, None) =>
151 include_str!("../modules/deviations/holo-ietf-ip-deviations.yang"),
152 EmbeddedModuleKey::new("holo-ietf-mpls-deviations", None, None, None) =>
153 include_str!("../modules/deviations/holo-ietf-mpls-deviations.yang"),
154 EmbeddedModuleKey::new("holo-ietf-key-chain-deviations", None, None, None) =>
155 include_str!("../modules/deviations/holo-ietf-key-chain-deviations.yang"),
156 EmbeddedModuleKey::new("holo-ietf-ospf-deviations", None, None, None) =>
157 include_str!("../modules/deviations/holo-ietf-ospf-deviations.yang"),
158 EmbeddedModuleKey::new("holo-ietf-ospf-sr-mpls-deviations", None, None, None) =>
159 include_str!("../modules/deviations/holo-ietf-ospf-sr-mpls-deviations.yang"),
160 EmbeddedModuleKey::new("holo-ietf-ospfv3-extended-lsa-deviations", None, None, None) =>
161 include_str!("../modules/deviations/holo-ietf-ospfv3-extended-lsa-deviations.yang"),
162 EmbeddedModuleKey::new("holo-ietf-rip-deviations", None, None, None) =>
163 include_str!("../modules/deviations/holo-ietf-rip-deviations.yang"),
164 EmbeddedModuleKey::new("holo-ietf-system-deviations", None, None, None) =>
165 include_str!("../modules/deviations/holo-ietf-system-deviations.yang"),
166 EmbeddedModuleKey::new("holo-ietf-routing-deviations", None, None, None) =>
167 include_str!("../modules/deviations/holo-ietf-routing-deviations.yang"),
168 EmbeddedModuleKey::new("holo-ietf-ipv6-unicast-routing-deviations", None, None, None) =>
169 include_str!("../modules/deviations/holo-ietf-ipv6-unicast-routing-deviations.yang"),
170 EmbeddedModuleKey::new("holo-ietf-routing-policy-deviations", None, None, None) =>
171 include_str!("../modules/deviations/holo-ietf-routing-policy-deviations.yang"),
172 EmbeddedModuleKey::new("holo-ietf-segment-routing-mpls-deviations", None, None, None) =>
173 include_str!("../modules/deviations/holo-ietf-segment-routing-mpls-deviations.yang"),
174 }
175});
176
177pub static YANG_IMPLEMENTED_MODULES: Lazy<Vec<&'static str>> =
182 Lazy::new(|| {
183 vec![
184 "ieee802-dot1q-types",
186 "iana-if-type",
188 "iana-bgp-notification",
189 "iana-bgp-rib-types",
190 "iana-bgp-types",
191 "ietf-bfd-ip-mh",
192 "ietf-bfd-ip-sh",
193 "ietf-bfd-types",
194 "ietf-bfd",
195 "ietf-bgp",
196 "ietf-bgp-policy",
197 "ietf-bier",
198 "ietf-routing-types",
199 "ietf-if-extensions",
200 "ietf-if-vlan-encapsulation",
201 "ietf-interfaces",
202 "ietf-ip",
203 "ietf-key-chain",
204 "ietf-routing",
205 "ietf-routing-policy",
206 "ietf-ipv4-unicast-routing",
207 "ietf-ipv6-unicast-routing",
208 "ietf-segment-routing",
209 "ietf-segment-routing-common",
210 "ietf-segment-routing-mpls",
211 "ietf-mpls",
212 "ietf-mpls-ldp",
213 "ietf-ospf",
214 "ietf-ospf-sr-mpls",
215 "ietf-ospfv3-extended-lsa",
216 "ietf-rip",
217 "ietf-system",
218 "ietf-tcp",
219 "holo-bgp",
221 "holo-ospf",
222 "holo-ospf-dev",
223 "holo-routing",
224 ]
225 });
226
227pub static YANG_FEATURES: Lazy<HashMap<&'static str, Vec<&'static str>>> =
229 Lazy::new(|| {
230 hashmap! {
231 "iana-bgp-types" => vec![
232 "clear-neighbors",
233 "route-refresh",
234 "ttl-security",
235 ],
236 "ietf-bfd-types" => vec![
237 "client-base-cfg-parms",
238 "single-minimum-interval",
239 ],
240 "ietf-key-chain" => vec![
241 "hex-key-string",
242 "independent-send-accept-lifetime",
243 ],
244 "ietf-if-extensions" => vec![
245 "sub-interfaces",
246 ],
247 "ietf-ospf" => vec![
248 "bfd",
249 "explicit-router-id",
250 "graceful-restart",
251 "ietf-spf-delay",
252 "key-chain",
253 "max-ecmp",
254 "mtu-ignore",
255 "ospfv3-authentication-trailer",
256 "stub-router",
257 ],
258 "ietf-rip" => vec![
259 "explicit-neighbors",
260 "global-statistics",
261 "interface-statistics",
262 ],
263 "ietf-segment-routing-common" => vec![
264 "sid-last-hop-behavior",
265 ],
266 }
267 });
268
269pub trait ToYang {
274 fn to_yang(&self) -> Cow<'static, str>;
276}
277
278pub trait ToYangBits {
279 fn to_yang_bits(&self) -> Vec<&'static str>;
281}
282
283pub trait TryFromYang: Sized {
284 fn try_from_yang(identity: &str) -> Option<Self>;
286}
287
288pub trait YangObject {
293 fn into_data_node(self: Box<Self>, dnode: &mut DataNodeRef<'_, '_>);
296
297 fn list_keys(&self) -> String {
300 String::new()
301 }
302}
303
304#[derive(Clone, Copy, Debug)]
311pub struct YangPath(&'static str);
312
313impl YangPath {
316 pub const fn new(path: &'static str) -> YangPath {
317 YangPath(path)
318 }
319
320 pub fn as_str(&self) -> &'static str {
321 self.0
322 }
323}
324
325impl std::fmt::Display for YangPath {
326 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
327 write!(f, "{}", self.0)
328 }
329}
330
331impl AsRef<str> for YangPath {
332 fn as_ref(&self) -> &str {
333 self.0
334 }
335}
336
337pub fn new_context() -> Context {
341 let mut ctx = Context::new(
342 ContextFlags::NO_YANGLIBRARY | ContextFlags::DISABLE_SEARCHDIRS,
343 )
344 .expect("Failed to create YANG context");
345 ctx.set_embedded_modules(&YANG_EMBEDDED_MODULES);
346 ctx
347}
348
349pub fn load_module(ctx: &mut Context, name: &str) {
351 let features = YANG_FEATURES
352 .get(name)
353 .map(|features| features.as_slice())
354 .unwrap_or_else(|| &[]);
355 if let Err(error) = ctx.load_module(name, None, features) {
356 panic!("failed to load YANG module: {}", error);
357 }
358}
359
360pub fn load_deviations(ctx: &mut Context, name: &str) {
362 let name = format!("holo-{}-deviations", name);
363 let _ = ctx.load_module(&name, None, &[]);
365}