diff --git a/README.md b/README.md index 4aad9b02..8f25ba22 100644 --- a/README.md +++ b/README.md @@ -217,6 +217,8 @@ Holo supports the following IETF RFCs and Internet drafts: | ietf-bfd@2022-09-22 | 100.00% | 100.00% | - | - | [100.00%](http://westphal.com.br/holo/ietf-bfd.html) | | ietf-bgp-policy@2023-07-05 | 100.00% | - | - | - | [100.00%](http://westphal.com.br/holo/ietf-bgp-policy.html) | | ietf-bgp@2023-07-05 | 32.38% | 87.86% | - | - | [61.39%](http://westphal.com.br/holo/ietf-bgp.html) | +| ietf-if-extensions@2023-01-26 | 100.00% | 0.00% | - | - | [50.00%](http://westphal.com.br/holo/ietf-if-extensions.html) | +| ietf-if-vlan-encapsulation@2023-01-26 | 42.86% | - | - | - | [42.86%](http://westphal.com.br/holo/ietf-if-vlan-encapsulation.html) | | ietf-interfaces@2018-01-09 | 100.00% | 0.00% | - | - | [22.22%](http://westphal.com.br/holo/ietf-interfaces.html) | | ietf-ip@2018-01-09 | 52.17% | 0.00% | - | - | [40.00%](http://westphal.com.br/holo/ietf-ip.html) | | ietf-ipv4-unicast-routing@2018-03-13 | 100.00% | 100.00% | - | - | [100.00%](http://westphal.com.br/holo/ietf-ipv4-unicast-routing.html) | diff --git a/holo-interface/src/interface.rs b/holo-interface/src/interface.rs index f596b43a..756c68cf 100644 --- a/holo-interface/src/interface.rs +++ b/holo-interface/src/interface.rs @@ -65,6 +65,7 @@ impl Interface { &self, ifindex: u32, netlink_handle: &rtnetlink::Handle, + interfaces: &Interfaces, ) { // Set administrative status. netlink::admin_status_change( @@ -74,6 +75,22 @@ impl Interface { ) .await; + // Create VLAN subinterface. + if let Some(vlan_id) = self.config.vlan_id + && self.ifindex.is_none() + && let Some(parent) = &self.config.parent + && let Some(parent) = interfaces.get_by_name(parent) + && let Some(parent_ifindex) = parent.ifindex + { + netlink::vlan_create( + netlink_handle, + self.name.clone(), + parent_ifindex, + vlan_id, + ) + .await; + } + // Set MTU. if let Some(mtu) = self.config.mtu { netlink::mtu_change(netlink_handle, ifindex, mtu).await; @@ -153,7 +170,9 @@ impl Interfaces { // configuration options. if iface.ifindex.is_none() { iface.ifindex = Some(ifindex); - iface.apply_config(ifindex, netlink_handle).await; + + let iface = &self.arena[iface_idx]; + iface.apply_config(ifindex, netlink_handle, self).await; } } None => { diff --git a/holo-interface/src/netlink.rs b/holo-interface/src/netlink.rs index 7682b490..d32952e5 100644 --- a/holo-interface/src/netlink.rs +++ b/holo-interface/src/netlink.rs @@ -204,6 +204,21 @@ pub(crate) async fn mtu_change(handle: &Handle, ifindex: u32, mtu: u32) { } } +pub(crate) async fn vlan_create( + handle: &Handle, + name: String, + parent_ifindex: u32, + vlan_id: u16, +) { + // Create netlink request. + let request = handle.link().add().vlan(name, parent_ifindex, vlan_id); + + // Execute request. + if let Err(error) = request.execute().await { + error!(%parent_ifindex, %vlan_id, %error, "failed to create VLAN interface"); + } +} + pub(crate) async fn addr_install( handle: &Handle, ifindex: u32, diff --git a/holo-interface/src/northbound/configuration.rs b/holo-interface/src/northbound/configuration.rs index 90cc8d40..6b4a3cc8 100644 --- a/holo-interface/src/northbound/configuration.rs +++ b/holo-interface/src/northbound/configuration.rs @@ -41,6 +41,7 @@ pub enum Event { InterfaceDelete(String), AdminStatusChange(String, bool), MtuChange(String, u32), + VlanCreate(String, u16), AddressInstall(String, IpNetwork), AddressUninstall(String, IpNetwork), } @@ -51,6 +52,8 @@ pub enum Event { pub struct InterfaceCfg { pub enabled: bool, pub mtu: Option, + pub parent: Option, + pub vlan_id: Option, pub addr_list: BTreeSet, } @@ -96,6 +99,31 @@ fn load_callbacks() -> Callbacks { let event_queue = args.event_queue; event_queue.insert(Event::AdminStatusChange(ifname, enabled)); }) + .path(interfaces::interface::parent_interface::PATH) + .modify_apply(|master, args| { + let ifname = args.list_entry.into_interface().unwrap(); + let parent = args.dnode.get_string(); + + let iface = master.interfaces.get_mut_by_name(&ifname).unwrap(); + iface.config.parent = Some(parent); + }) + .delete_apply(|master, args| { + let ifname = args.list_entry.into_interface().unwrap(); + + let iface = master.interfaces.get_mut_by_name(&ifname).unwrap(); + iface.config.parent = None; + }) + .path(interfaces::interface::encapsulation::dot1q_vlan::outer_tag::vlan_id::PATH) + .modify_apply(|master, args| { + let ifname = args.list_entry.into_interface().unwrap(); + let vlan_id = args.dnode.get_u16(); + + let iface = master.interfaces.get_mut_by_name(&ifname).unwrap(); + iface.config.vlan_id = Some(vlan_id); + + let event_queue = args.event_queue; + event_queue.insert(Event::VlanCreate(ifname, vlan_id)); + }) .path(interfaces::interface::ipv4::PATH) .create_apply(|_context, _args| { // TODO: implement me! @@ -288,6 +316,24 @@ impl Provider for Master { .await; } } + Event::VlanCreate(ifname, vlan_id) => { + // If the parent interface is active, create VLAN subinterface + // using the netlink handle. + if let Some(iface) = self.interfaces.get_by_name(&ifname) + && iface.ifindex.is_none() + && let Some(parent) = &iface.config.parent + && let Some(parent) = self.interfaces.get_by_name(parent) + && let Some(parent_ifindex) = parent.ifindex + { + netlink::vlan_create( + &self.netlink_handle, + iface.name.clone(), + parent_ifindex, + vlan_id, + ) + .await; + } + } Event::AddressInstall(ifname, addr) => { // If the interface is active, install the address using the // netlink handle. @@ -325,6 +371,8 @@ impl Default for InterfaceCfg { InterfaceCfg { enabled, mtu: None, + parent: None, + vlan_id: None, addr_list: Default::default(), } } diff --git a/holo-interface/src/northbound/mod.rs b/holo-interface/src/northbound/mod.rs index d8b02c9d..dcb2034d 100644 --- a/holo-interface/src/northbound/mod.rs +++ b/holo-interface/src/northbound/mod.rs @@ -17,7 +17,12 @@ use crate::Master; impl ProviderBase for Master { fn yang_modules() -> &'static [&'static str] { - &["ietf-interfaces", "ietf-ip"] + &[ + "ietf-if-extensions", + "ietf-if-vlan-encapsulation", + "ietf-interfaces", + "ietf-ip", + ] } fn top_level_node(&self) -> String { diff --git a/holo-tools/yang-coverage.sh b/holo-tools/yang-coverage.sh index 91289ed1..446bd24b 100755 --- a/holo-tools/yang-coverage.sh +++ b/holo-tools/yang-coverage.sh @@ -2,6 +2,8 @@ cargo run --bin yang_coverage --\ -m ietf-interfaces\ + -m ietf-if-extensions\ + -m ietf-if-vlan-encapsulation\ -m ietf-ip\ -m ietf-ipv4-unicast-routing\ -m ietf-ipv6-unicast-routing\ diff --git a/holo-yang/modules/deviations/ietf-if-extensions-holo-deviations.yang b/holo-yang/modules/deviations/ietf-if-extensions-holo-deviations.yang new file mode 100644 index 00000000..f598ee60 --- /dev/null +++ b/holo-yang/modules/deviations/ietf-if-extensions-holo-deviations.yang @@ -0,0 +1,28 @@ +module ietf-if-extensions-holo-deviations { + yang-version 1.1; + namespace "http://holo-routing.org/yang/ietf-if-extensions-holo-deviations"; + prefix ietf-if-extensions-holo-deviations; + + import ietf-interfaces { + prefix if; + } + + import ietf-if-extensions { + prefix if-ext; + } + + organization + "Holo Routing Stack"; + + description + "This module defines deviation statements for the ietf-if-extensions + module."; + + deviation "/if:interfaces/if:interface/if:statistics/if-ext:in-discard-unknown-encaps" { + deviate not-supported; + } + + deviation "/if:interfaces/if:interface/if-ext:forwarding-mode" { + deviate not-supported; + } +} diff --git a/holo-yang/modules/deviations/ietf-if-vlan-encapsulation-holo-deviations.yang b/holo-yang/modules/deviations/ietf-if-vlan-encapsulation-holo-deviations.yang new file mode 100644 index 00000000..cfaeb083 --- /dev/null +++ b/holo-yang/modules/deviations/ietf-if-vlan-encapsulation-holo-deviations.yang @@ -0,0 +1,51 @@ +module ietf-if-vlan-encapsulation-holo-deviations { + yang-version 1.1; + namespace "http://holo-routing.org/yang/ietf-if-vlan-encapsulation-holo-deviations"; + prefix ietf-if-vlan-encapsulation-holo-deviations; + + import ietf-interfaces { + prefix if; + } + + import ietf-if-extensions { + prefix if-ext; + } + + import ietf-if-vlan-encapsulation { + prefix if-vlan; + } + + organization + "Holo Routing Stack"; + + description + "This module defines deviation statements for the ietf-if-vlan-encapsulation + module."; + + deviation "/if:interfaces/if:interface/if-ext:encapsulation/if-ext:encaps-type/if-vlan:dot1q-vlan/if-vlan:dot1q-vlan/if-vlan:outer-tag" { + deviate delete { + must 'tag-type = "dot1q-types:s-vlan" or ' + + 'tag-type = "dot1q-types:c-vlan"'; + } + } + + deviation "/if:interfaces/if:interface/if-ext:encapsulation/if-ext:encaps-type/if-vlan:dot1q-vlan/if-vlan:dot1q-vlan/if-vlan:outer-tag/if-vlan:tag-type" { + deviate not-supported; + } + + deviation "/if:interfaces/if:interface/if-ext:encapsulation/if-ext:encaps-type/if-vlan:dot1q-vlan/if-vlan:dot1q-vlan/if-vlan:second-tag" { + deviate not-supported; + } + + /* + deviation "/if:interfaces/if:interface/if-ext:encapsulation/if-ext:encaps-type/if-vlan:dot1q-vlan/if-vlan:dot1q-vlan/if-vlan:second-tag/if-vlan:tag-type" { + deviate not-supported; + } + */ + + /* + deviation "/if:interfaces/if:interface/if-ext:encapsulation/if-ext:encaps-type/if-vlan:dot1q-vlan/if-vlan:dot1q-vlan/if-vlan:second-tag/if-vlan:vlan-id" { + deviate not-supported; + } + */ +} diff --git a/holo-yang/modules/ieee/ieee802-dot1q-types@2022-01-19.yang b/holo-yang/modules/ieee/ieee802-dot1q-types@2022-01-19.yang new file mode 100644 index 00000000..cfc46ed9 --- /dev/null +++ b/holo-yang/modules/ieee/ieee802-dot1q-types@2022-01-19.yang @@ -0,0 +1,980 @@ +module ieee802-dot1q-types { + namespace urn:ieee:std:802.1Q:yang:ieee802-dot1q-types; + prefix dot1q-types; + import ietf-yang-types { + prefix yang; + } + organization + "IEEE 802.1 Working Group"; + contact + "WG-URL: http://ieee802.org/1/ + WG-EMail: stds-802-1-l@ieee.org + + Contact: IEEE 802.1 Working Group Chair + Postal: C/O IEEE 802.1 Working Group + IEEE Standards Association + 445 Hoes Lane + Piscataway, NJ 08854 + USA + + E-mail: stds-802-1-chairs@ieee.org"; + description + "Common types used within dot1Q-bridge modules. + + Copyright (C) IEEE (2022). + + This version of this YANG module is part of IEEE Std 802.1Q; see the + standard itself for full legal notices."; + revision 2022-01-19 { + description + "Published as part of IEEE Std 802.1Q-2022."; + reference + "IEEE Std 802.1Q-2022, Bridges and Bridged Networks."; + } + revision 2020-06-04 { + description + "Published as part of IEEE Std 802.1Qcx-2020. Second version."; + reference + "IEEE Std 802.1Qcx-2020, Bridges and Bridged Networks - YANG Data + Model for Connectivity Fault Management."; + } + revision 2018-03-07 { + description + "Published as part of IEEE Std 802.1Q-2018. Initial version."; + reference + "IEEE Std 802.1Q-2018, Bridges and Bridged Networks."; + } + identity dot1q-vlan-type { + description + "Base identity from which all 802.1Q VLAN tag types are derived + from."; + } + identity c-vlan { + base dot1q-vlan-type; + description + "An 802.1Q Customer VLAN, using the 81-00 EtherType"; + reference + "5.5 of IEEE Std 802.1Q-2022"; + } + identity s-vlan { + base dot1q-vlan-type; + description + "An 802.1Q Service VLAN, using the 88-A8 EtherType originally + introduced in 802.1ad, and incorporated into 802.1Q (2011)"; + reference + "5.6 of IEEE Std 802.1Q-2022"; + } + identity transmission-selection-algorithm { + description + "Specify the transmission selection algorithms of IEEE Std + 802.1Q-2022 Table 8-6"; + } + identity strict-priority { + base transmission-selection-algorithm; + description + "Indicates the strict priority transmission selection algorithm."; + reference + "Table 8-6 of IEEE Std 802.1Q-2022"; + } + identity credit-based-shaper { + base transmission-selection-algorithm; + description + "Indicates the credit based shaper transmission selection + algorithm."; + reference + "Table 8-6 of IEEE Std 802.1Q-2022"; + } + identity enhanced-transmission-selection { + base transmission-selection-algorithm; + description + "Indicates the enhanced transmission selection algorithm."; + reference + "Table 8-6 of IEEE Std 802.1Q-2022"; + } + identity asynchronous-traffic-shaping { + base transmission-selection-algorithm; + description + "Indicates the asynchronous transmission selection algorithm."; + reference + "Table 8-6 of IEEE Std 802.1Q-2022"; + } + identity vendor-specific { + base transmission-selection-algorithm; + description + "Indicates a vendor specific transmission selection algorithm."; + reference + "Table 8-6 of IEEE Std 802.1Q-2022"; + } + typedef name-type { + type string { + length "0..32"; + } + description + "A text string of up to 32 characters, of locally determined + significance."; + } + typedef port-number-type { + type uint32 { + range "1..4095"; + } + description + "The port number of the Bridge port for which this entry contains + Bridge management information."; + } + typedef priority-type { + type uint8 { + range "0..7"; + } + description + "A range of priorities from 0 to 7 (inclusive). The Priority Code + Point (PCP) is a 3-bit field that refers to the class of service + associated with an 802.1Q VLAN tagged frame. The field specifies a + priority value between 0 and 7, these values can be used by + quality of service (QoS) to prioritize different classes of + traffic."; + } + typedef vid-range-type { + type string { + pattern + "([1-9]"+ + "[0-9]{0,3}"+ + "(-[1-9][0-9]{0,3})?"+ + "(,[1-9][0-9]{0,3}(-[1-9][0-9]{0,3})?)*)"; + } + description + "A list of VLAN Ids, or non overlapping VLAN ranges, in ascending + order, between 1 and 4094. + + This type is used to match an ordered list of VLAN Ids, or + contiguous ranges of VLAN Ids. Valid VLAN Ids must be in the range + 1 to 4094, and included in the list in non overlapping ascending + order. + + For example: 1,10-100,250,500-1000"; + } + typedef vlanid { + type uint16 { + range "1..4094"; + } + description + "The vlanid type uniquely identifies a VLAN. This is the 12-bit + VLAN-ID used in the VLAN Tag header. The range is defined by the + referenced specification. This type is in the value set and its + semantics equivalent to the VlanId textual convention of the + SMIv2."; + } + typedef vlan-index-type { + type uint32 { + range "1..4094 | 4096..4294967295"; + } + description + "A value used to index per-VLAN tables. Values of 0 and 4095 are + not permitted. The range of valid VLAN indices. If the value is + greater than 4095, then it represents a VLAN with scope local to + the particular agent, i.e., one without a global VLAN-ID assigned + to it. Such VLANs are outside the scope of IEEE 802.1Q, but it is + convenient to be able to manage them in the same way using this + YANG module."; + reference + "9.6 of IEEE Std 802.1Q-2022"; + } + typedef mstid-type { + type uint32 { + range "1..4094"; + } + description + "In an MSTP Bridge, an MSTID, i.e., a value used to identify a + spanning tree (or MST) instance"; + reference + "13.8 of IEEE Std 802.1Q-2022"; + } + typedef pcp-selection-type { + type enumeration { + enum 8P0D { + description + "8 priorities, 0 drop eligible"; + } + enum 7P1D { + description + "7 priorities, 1 drop eligible"; + } + enum 6P2D { + description + "6 priorities, 2 drop eligible"; + } + enum 5P3D { + description + "5 priorities, 3 drop eligible"; + } + } + description + "Priority Code Point selection types."; + reference + "12.6.2.5.3, 6.9.3 of IEEE Std 802.1Q-2022"; + } + typedef protocol-frame-format-type { + type enumeration { + enum Ethernet { + description + "Ethernet frame format"; + } + enum rfc1042 { + description + "RFC 1042 frame format"; + } + enum snap8021H { + description + "SNAP 802.1H frame format"; + } + enum snapOther { + description + "Other SNAP frame format"; + } + enum llcOther { + description + "Other LLC frame format"; + } + } + description + "A value representing the frame format to be matched."; + reference + "12.10.1.7.1 of IEEE Std 802.1Q-2022"; + } + typedef ethertype-type { + type string { + pattern "[0-9a-fA-F]{2}-[0-9a-fA-F]{2}"; + } + description + "The EtherType value represented in the canonical order defined by + IEEE 802. The canonical representation uses uppercase characters."; + reference + "9.2 of IEEE Std 802-2014"; + } + typedef dot1q-tag-type { + type identityref { + base dot1q-vlan-type; + } + description + "Identifies a specific 802.1Q tag type"; + reference + "9.5 IEEE Std 802.1Q-2022"; + } + typedef traffic-class-type { + type uint8 { + range "0..7"; + } + description + "This is the numerical value associated with a traffic class in a + Bridge. Larger values are associated with higher priority traffic + classes."; + reference + "3.273 of IEEE Std 802.1Q-2022"; + } + grouping dot1q-tag-classifier-grouping { + description + "A grouping which represents an 802.1Q VLAN, matching both the + EtherType and a single VLAN Id."; + leaf tag-type { + type dot1q-tag-type; + mandatory true; + description + "VLAN type"; + } + leaf vlan-id { + type vlanid; + mandatory true; + description + "VLAN Id"; + } + } + grouping dot1q-tag-or-any-classifier-grouping { + description + "A grouping which represents an 802.1Q VLAN, matching both the + EtherType and a single VLAN Id or 'any' to match on any VLAN Id."; + leaf tag-type { + type dot1q-tag-type; + mandatory true; + description + "VLAN type"; + } + leaf vlan-id { + type union { + type vlanid; + type enumeration { + enum any { + value 4095; + description + "Matches 'any' VLAN in the range 1 to 4094 that is not + matched by a more specific VLAN Id match"; + } + } + } + mandatory true; + description + "VLAN Id or any"; + } + } + grouping dot1q-tag-ranges-classifier-grouping { + description + "A grouping which represents an 802.1Q VLAN that matches a range + of VLAN Ids."; + leaf tag-type { + type dot1q-tag-type; + mandatory true; + description + "VLAN type"; + } + leaf vlan-ids { + type vid-range-type; + mandatory true; + description + "VLAN Ids"; + } + } + grouping dot1q-tag-ranges-or-any-classifier-grouping { + description + "A grouping which represents an 802.1Q VLAN, matching both the + EtherType and a single VLAN Id, ordered list of ranges, or 'any' + to match on any VLAN Id."; + leaf tag-type { + type dot1q-tag-type; + mandatory true; + description + "VLAN type"; + } + leaf vlan-id { + type union { + type vid-range-type; + type enumeration { + enum any { + value 4095; + description + "Matches 'any' VLAN in the range 1 to 4094."; + } + } + } + mandatory true; + description + "VLAN Ids or any"; + } + } + grouping priority-regeneration-table-grouping { + description + "The priority regeneration table provides the ability to map + incoming priority values on a per-Port basis, under management + control."; + reference + "6.9.4 of IEEE Std 802.1Q-2022"; + leaf priority0 { + type priority-type; + default "0"; + description + "Priority 0"; + reference + "12.6.2.3, 6.9.4 of IEEE Std 802.1Q-2022"; + } + leaf priority1 { + type priority-type; + default "1"; + description + "Priority 1"; + reference + "12.6.2.3, 6.9.4 of IEEE Std 802.1Q-2022"; + } + leaf priority2 { + type priority-type; + default "2"; + description + "Priority 2"; + reference + "12.6.2.3, 6.9.4 of IEEE Std 802.1Q-2022"; + } + leaf priority3 { + type priority-type; + default "3"; + description + "Priority 3"; + reference + "12.6.2.3, 6.9.4 of IEEE Std 802.1Q-2022"; + } + leaf priority4 { + type priority-type; + default "4"; + description + "Priority 4"; + reference + "12.6.2.3, 6.9.4 of IEEE Std 802.1Q-2022"; + } + leaf priority5 { + type priority-type; + default "5"; + description + "Priority 5"; + reference + "12.6.2.3, 6.9.4 of IEEE Std 802.1Q-2022"; + } + leaf priority6 { + type priority-type; + default "6"; + description + "Priority 6"; + reference + "12.6.2.3, 6.9.4 of IEEE Std 802.1Q-2022"; + } + leaf priority7 { + type priority-type; + default "7"; + description + "Priority 7"; + reference + "12.6.2.3, 6.9.4 of IEEE Std 802.1Q-2022"; + } + } + grouping pcp-decoding-table-grouping { + description + "The Priority Code Point decoding table enables the decoding of + the priority and drop-eligible parameters from the PCP."; + reference + "6.9.3 of IEEE Std 802.1Q-2022"; + list pcp-decoding-map { + key "pcp"; + description + "This map associates the priority code point field found in the + VLAN to a priority and drop eligible value based upon the + priority code point selection type."; + leaf pcp { + type pcp-selection-type; + description + "The priority code point selection type."; + reference + "12.6.2.7, 6.9.3 of IEEE Std 802.1Q-2022"; + } + list priority-map { + key "priority-code-point"; + description + "This map associated a priority code point value to priority + and drop eligible parameters."; + leaf priority-code-point { + type priority-type; + description + "Priority associated with the pcp."; + reference + "12.6.2.7, 6.9.3 of IEEE Std 802.1Q-2022"; + } + leaf priority { + type priority-type; + description + "Priority associated with the pcp."; + reference + "12.6.2.7, 6.9.3 of IEEE Std 802.1Q-2022"; + } + leaf drop-eligible { + type boolean; + description + "Drop eligible value for pcp"; + reference + "12.6.2.7, 6.9.3 of IEEE Std 802.1Q-2022"; + } + } + } + } + grouping pcp-encoding-table-grouping { + description + "The Priority Code Point encoding table encodes the priority and + drop-eligible parameters in the PCP field of the VLAN tag."; + reference + "12.6.2.9, 6.9.3 of IEEE Std 802.1Q-2022"; + list pcp-encoding-map { + key "pcp"; + description + "This map associated the priority and drop-eligible parameters + to the priority used to encode the PCP of the VLAN based upon + the priority code point selection type."; + leaf pcp { + type pcp-selection-type; + description + "The priority code point selection type."; + reference + "12.6.2.7, 6.9.3 of IEEE Std 802.1Q-2022"; + } + list priority-map { + key "priority dei"; + description + "This map associated the priority and drop-eligible parameters + to the priority code point field of the VLAN tag."; + leaf priority { + type priority-type; + description + "Priority associated with the pcp."; + reference + "12.6.2.7, 6.9.3 of IEEE Std 802.1Q-2022"; + } + leaf dei { + type boolean; + description + "The drop eligible value."; + reference + "12.6.2, 8.6.6 of IEEE Std 802.1Q-2022"; + } + leaf priority-code-point { + type priority-type; + description + "PCP value for priority when DEI value"; + reference + "12.6.2.9, 6.9.3 of IEEE Std 802.1Q-2022"; + } + } + } + } + grouping service-access-priority-table-grouping { + description + "The Service Access Priority Table associates a received priority + with a serice access priority."; + reference + "12.6.2.17, 6.13.1 of IEEE Std 802.1Q-2022"; + leaf priority0 { + type priority-type; + default "0"; + description + "Service access priority value for priority 0"; + reference + "12.6.2.17, 6.13.1 of IEEE Std 802.1Q-2022"; + } + leaf priority1 { + type priority-type; + default "1"; + description + "Service access priority value for priority 1"; + reference + "12.6.2.17, 6.13.1 of IEEE Std 802.1Q-2022"; + } + leaf priority2 { + type priority-type; + default "2"; + description + "Service access priority value for priority 2"; + reference + "12.6.2.17, 6.13.1 of IEEE Std 802.1Q-2022"; + } + leaf priority3 { + type priority-type; + default "3"; + description + "Service access priority value for priority 3"; + reference + "12.6.2.17, 6.13.1 of IEEE Std 802.1Q-2022"; + } + leaf priority4 { + type priority-type; + default "4"; + description + "Service access priority value for priority 4"; + reference + "12.6.2.17, 6.13.1 of IEEE Std 802.1Q-2022"; + } + leaf priority5 { + type priority-type; + default "5"; + description + "Service access priority value for priority 5"; + reference + "12.6.2.17, 6.13.1 of IEEE Std 802.1Q-2022"; + } + leaf priority6 { + type priority-type; + default "6"; + description + "Service access priority value for priority 6"; + reference + "12.6.2.17, 6.13.1 of IEEE Std 802.1Q-2022"; + } + leaf priority7 { + type priority-type; + default "7"; + description + "Service access priority value for priority 7"; + reference + "12.6.2.17, 6.13.1 of IEEE Std 802.1Q-2022"; + } + } + grouping traffic-class-table-grouping { + description + "The Traffic Class Table models the operations that can be + performed on, or inquire about, the current contents of the + Traffic Class Table (8.6.6) for a given Port."; + reference + "12.6.3, 8.6.6 of IEEE Std 802.1Q-2022"; + list traffic-class-map { + key "priority"; + description + "The priority index into the traffic class table."; + leaf priority { + type priority-type; + description + "The priority of the traffic class entry."; + reference + "8.6.6 of IEEE Std 802.1Q-2022"; + } + list available-traffic-class { + key "num-traffic-class"; + description + "The traffic class index associated with a given priority + within the traffic class table."; + reference + "8.6.6 of IEEE Std 802.1Q-2022"; + leaf num-traffic-class { + type uint8 { + range "1..8"; + } + description + "The available number of traffic classes."; + reference + "8.6.6 of IEEE Std 802.1Q-2022"; + } + leaf traffic-class { + type traffic-class-type; + description + "The traffic class index associated with a given traffic + class entry."; + reference + "8.6.6 of IEEE Std 802.1Q-2022"; + } + } + } + } + grouping transmission-selection-table-grouping { + description + "The Transmission Selection Algorithm Table models the operations + that can be performed on, or inquire about, the current contents + of the Transmission Selection Algorithm Table (12.20.2) for a + given Port."; + reference + "12.20.2, 8.6.8 of IEEE Std 802.1Q-2022"; + list transmission-selection-algorithm-map { + key "traffic-class"; + description + "The traffic class to index into the transmission selection + table."; + leaf traffic-class { + type traffic-class-type; + description + "The traffic class of the entry."; + reference + "8.6.6 of IEEE Std 802.1Q-2022"; + } + leaf transmission-selection-algorithm { + type identityref { + base dot1q-types:transmission-selection-algorithm; + } + description + "Transmission selection algorithm"; + reference + "8.6.8, Table 8-6 of IEEE Std 802.1Q-2022"; + } + } + } + grouping port-map-grouping { + description + "A set of control indicators, one for each Port. A Port Map, + containing a control element for each outbound Port"; + reference + "8.8.1, 8.8.2 of IEEE Std 802.1Q-2022"; + list port-map { + key "port-ref"; + description + "The list of entries composing the port map."; + leaf port-ref { + type port-number-type; + description + "The interface port reference associated with this map."; + reference + "8.8.1 of IEEE Std 802.1Q-2022"; + } + choice map-type { + description + "Type of port map"; + container static-filtering-entries { + description + "Static filtering entries attributes."; + leaf control-element { + type enumeration { + enum forward { + description + "Forwarded, independently of any dynamic filtering + information held by the FDB."; + } + enum filter { + description + "Filtered, independently of any dynamic filtering + information."; + } + enum forward-filter { + description + "Forwarded or filtered on the basis of dynamic + filtering information, or on the basis of the default + Group filtering behavior for the outbound Port (8.8.6) + if no dynamic filtering information is present + specifically for the MAC address."; + } + } + description + "containing a control element for each outbound Port, + specifying that a frame with a destination MAC address, + and in the case of VLAN Bridge components, VID that meets + this specification."; + reference + "8.8.1 of IEEE Std 802.1Q-2022"; + } + leaf connection-identifier { + type port-number-type; + description + "A Port MAP may contain a connection identifier (8.8.12) + for each outbound port. The connection identifier may be + associated with the Bridge Port value maintained in a + Dynamic Filtering Entry of the FDB for Bridge Ports."; + reference + "8.8.1, 8.8.12 of IEEE Std 802.1Q-2022"; + } + } + container static-vlan-registration-entries { + description + "Static VLAN registration entries."; + leaf registrar-admin-control { + type enumeration { + enum fixed-new-ignored { + description + "Registration Fixed (New ignored)."; + } + enum fixed-new-propagated { + description + "Registration Fixed (New propagated."; + } + enum forbidden { + description + "Registration Forbidden."; + } + enum normal { + description + "Normal Registration."; + } + } + description + "The Registrar Administrative Control values for MVRP and + MIRP for the VID."; + reference + "8.8.2 of IEEE Std 802.1Q-2022"; + } + leaf vlan-transmitted { + type enumeration { + enum tagged { + description + "VLAN-tagged"; + } + enum untagged { + description + "VLAN-untagged"; + } + } + description + "Whether frames are to be VLAN-tagged or untagged when + transmitted."; + reference + "8.8.2 of IEEE Std 802.1Q-2022"; + } + } + container mac-address-registration-entries { + description + "MAC address registration entries attributes."; + leaf control-element { + type enumeration { + enum registered { + description + "Forwarded, independently of any dynamic filtering + information held by the FDB."; + } + enum not-registered { + description + "Filtered, independently of any dynamic filtering + information."; + } + } + description + "containing a control element for each outbound Port, + specifying that a frame with a destination MAC address, + and in the case of VLAN Bridge components, VID that meets + this specification."; + reference + "8.8.4 of IEEE Std 802.1Q-2022"; + } + } + container dynamic-vlan-registration-entries { + description + "Dynamic VLAN registration entries attributes."; + leaf control-element { + type enumeration { + enum registered { + description + "Forwarded, independently of any dynamic filtering + information held by the FDB."; + } + } + description + "containing a control element for each outbound Port, + specifying that a frame with a destination MAC address, + and in the case of VLAN Bridge components, VID that meets + this specification."; + reference + "8.8.5 of IEEE Std 802.1Q-2022"; + } + } + container dynamic-reservation-entries { + description + "Dynamic reservation entries attributes."; + leaf control-element { + type enumeration { + enum forward { + description + "Forwarded, independently of any dynamic filtering + information held by the FDB."; + } + enum filter { + description + "Filtered, independently of any dynamic filtering + information."; + } + } + description + "Containing a control element for each outbound Port, + specifying that a frame with a destination MAC address, + and in the case of VLAN Bridge components, VID that meets + this specification."; + reference + "8.8.7 of IEEE Std 802.1Q-2022"; + } + } + container dynamic-filtering-entries { + description + "Dynamic filtering entries attributes."; + leaf control-element { + type enumeration { + enum forward { + description + "Forwarded, independently of any dynamic filtering + information held by the FDB."; + } + } + description + "Containing a control element for each outbound Port, + specifying that a frame with a destination MAC address, + and in the case of VLAN Bridge components, VID that meets + this specification."; + reference + "8.8.3 of IEEE Std 802.1Q-2022"; + } + } + } + } + } + grouping bridge-port-statistics-grouping { + description + "Grouping of bridge port statistics."; + reference + "12.6.1.1.3 of IEEE Std 802.1Q-2022"; + leaf delay-exceeded-discards { + type yang:counter64; + description + "The number of frames discarded by this port due to excessive + transit delay through the Bridge. It is incremented by both + transparent and source route Bridges."; + reference + "12.6.1.1.3, 8.6.6 of IEEE Std 802.1Q-2022"; + } + leaf mtu-exceeded-discards { + type yang:counter64; + description + "The number of frames discarded by this port due to an excessive + size. It is incremented by both transparent and source route + Bridges."; + reference + "Item g) in 12.6.1.1.3 of IEEE Std 802.1Q-2022"; + } + leaf frame-rx { + type yang:counter64; + description + "The number of frames that have been received by this port from + its segment. Note that a frame received on the interface + corresponding to this port is only counted by this object if and + only if it is for a protocol being processed by the local + bridging function, including Bridge management frames."; + reference + "12.6.1.1.3 of IEEE Std 802.1Q-2022"; + } + leaf octets-rx { + type yang:counter64; + description + "The total number of octets in all valid frames received + (including BPDUs, frames addressed to the Bridge as an end + station, and frames that were submitted to the Forwarding + Process)."; + reference + "12.6.1.1.3 of IEEE Std 802.1Q-2022"; + } + leaf frame-tx { + type yang:counter64; + description + "The number of frames that have been transmitted by this port to + its segment. Note that a frame transmitted on the interface + corresponding to this port is only counted by this object if and + only if it is for a protocol being processed by the local + bridging function, including Bridge management frames."; + } + leaf octets-tx { + type yang:counter64; + description + "The total number of octets that have been transmitted by this + port to its segment."; + } + leaf discard-inbound { + type yang:counter64; + description + "Count of received valid frames that were discarded (i.e., + filtered) by the Forwarding Process."; + reference + "12.6.1.1.3 of IEEE Std 802.1Q-2022"; + } + leaf forward-outbound { + type yang:counter64; + description + "The number of frames forwarded to the associated MAC Entity + (8.5)."; + reference + "12.6.1.1.3 of IEEE Std 802.1Q-2022"; + } + leaf discard-lack-of-buffers { + type yang:counter64; + description + "The count of frames that were to be transmitted through the + associated Port but were discarded due to lack of buffers."; + reference + "12.6.1.1.3 of IEEE Std 802.1Q-2022"; + } + leaf discard-transit-delay-exceeded { + type yang:counter64; + description + "The number of frames discarded by this port due to excessive + transit delay through the Bridge. It is incremented by both + transparent and source route Bridges."; + reference + "12.6.1.1.3 of IEEE Std 802.1Q-2022"; + } + leaf discard-on-error { + type yang:counter64; + description + "The number of frames that were to be forwarded on the + associated MAC but could not be transmitted (e.g., frame would + be too large, 6.5.8)."; + reference + "12.6.1.1.3 of IEEE Std 802.1Q-2022"; + } + } +} diff --git a/holo-yang/modules/ietf/ietf-if-extensions@2023-01-26.yang b/holo-yang/modules/ietf/ietf-if-extensions@2023-01-26.yang new file mode 100644 index 00000000..fdcb0bcc --- /dev/null +++ b/holo-yang/modules/ietf/ietf-if-extensions@2023-01-26.yang @@ -0,0 +1,535 @@ +module ietf-if-extensions { + yang-version 1.1; + + namespace "urn:ietf:params:xml:ns:yang:ietf-if-extensions"; + + prefix if-ext; + + import ietf-yang-types { + prefix yang; + reference "RFC 6991: Common YANG Data Types"; + } + + import ietf-interfaces { + prefix if; + reference + "RFC 8343: A YANG Data Model For Interface Management"; + } + + import iana-if-type { + prefix ianaift; + reference "RFC 7224: IANA Interface Type YANG Module"; + } + + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + + contact + "WG Web: + WG List: + + Editor: Robert Wilton + "; + + description + "This module contains common definitions for extending the IETF + interface YANG model (RFC 8343) with common configurable layer 2 + properties. + + Copyright (c) 2023 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject to + the license terms contained in, the Revised BSD License set + forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC XXXX + (https://www.rfc-editor.org/info/rfcXXXX); see the RFC itself + for full legal notices. + + The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL + NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED', + 'MAY', and 'OPTIONAL' in this document are to be interpreted as + described in BCP 14 (RFC 2119) (RFC 8174) when, and only when, + they appear in all capitals, as shown here."; + + revision 2023-01-26 { + description + "Initial revision."; + + reference + "RFC XXXX, Common Interface Extension YANG Data Models"; + } + + feature link-flap-suppression { + description + "This feature indicates that configurable interface link + delay is supported, which is a feature is used to limit the + propagation of very short interface link state flaps."; + reference "RFC XXXX, Section 2.1 Link Flap Suppression"; + } + + feature dampening { + description + "This feature indicates that the device supports interface + dampening, which is a feature that is used to limit the + propagation of interface link state flaps over longer + periods."; + reference "RFC XXXX, Section 2.2 Dampening"; + } + + feature loopback { + description + "This feature indicates that configurable interface loopback is + supported."; + reference "RFC XXXX, Section 2.4 Loopback"; + } + + feature max-frame-size { + description + "This feature indicates that the device supports configuring or + reporting the maximum frame size on interfaces."; + reference "RFC XXXX, Section 2.5 Maximum Frame Size"; + } + + feature sub-interfaces { + description + "This feature indicates that the device supports the + instantiation of sub-interfaces. Sub-interfaces are defined + as logical child interfaces that allow features and forwarding + decisions to be applied to a subset of the traffic processed + on the specified parent interface."; + reference "RFC XXXX, Section 2.6 Sub-interface"; + } + + /* + * Define common identities to help allow interface types to be + * assigned properties. + */ + identity sub-interface { + description + "Base type for generic sub-interfaces. + + New or custom interface types can derive from this type to + inherit generic sub-interface configuration."; + reference "RFC XXXX, Section 2.6 Sub-interface"; + } + + identity ethSubInterface{ + base ianaift:l2vlan; + base sub-interface; + + description + "This identity represents the child sub-interface of any + interface types that uses Ethernet framing (with or without + 802.1Q tagging)."; + } + + identity loopback { + description "Base identity for interface loopback options"; + reference "RFC XXXX, Section 2.4"; + } + identity internal { + base loopback; + description + "All egress traffic on the interface is internally looped back + within the interface to be received on the ingress path."; + reference "RFC XXXX, Section 2.4"; + } + identity line { + base loopback; + description + "All ingress traffic received on the interface is internally + looped back within the interface to the egress path."; + reference "RFC XXXX, Section 2.4"; + } + identity connector { + base loopback; + description + "The interface has a physical loopback connector attached that + loops all egress traffic back into the interface's ingress + path, with equivalent semantics to loopback internal."; + reference "RFC XXXX, Section 2.4"; + } + + identity forwarding-mode { + description "Base identity for forwarding-mode options."; + reference "RFC XXXX, Section 2.7"; + } + identity physical { + base forwarding-mode; + description + "Physical layer forwarding. This includes DWDM or OTN based + optical switching."; + reference "RFC XXXX, Section 2.7"; + } + identity data-link { + base forwarding-mode; + description + "Layer 2 based forwarding, such as Ethernet/VLAN based + switching, or L2VPN services."; + reference "RFC XXXX, Section 2.7"; + } + identity network { + base forwarding-mode; + description + "Network layer based forwarding, such as IP, MPLS, or L3VPNs."; + reference "RFC XXXX, Section 2.7"; + } + + /* + * Augments the IETF interfaces model with leaves to configure + * and monitor link-flap-suppression on an interface. + */ + augment "/if:interfaces/if:interface" { + description + "Augments the IETF interface model with optional common + interface level commands that are not formally covered by any + specific standard."; + + /* + * Defines standard YANG for the Link Flap Suppression feature. + */ + container link-flap-suppression { + if-feature "link-flap-suppression"; + description + "Holds link flap related feature configuration."; + leaf down { + type uint32; + units milliseconds; + description + "Delays the propagation of a 'loss of carrier signal' event + that would cause the interface state to go down, i.e. the + command allows short link flaps to be suppressed. The + configured value indicates the minimum time interval (in + milliseconds) that the link signal must be continuously + down before the interface state is brought down. If not + configured, the behavior on loss of link signal is + vendor/interface specific, but with the general + expectation that there should be little or no delay."; + } + leaf up { + type uint32; + units milliseconds; + description + "Defines the minimum time interval (in milliseconds) that + the link signal must be continuously present and error + free before the interface state is allowed to transition + from down to up. If not configured, the behavior is + vendor/interface specific, but with the general + expectation that sufficient default delay should be used + to ensure that the interface is stable when enabled before + being reported as being up. Configured values that are + too low for the hardware capabilties may be rejected."; + } + leaf carrier-transitions { + type yang:counter64; + units transitions; + config false; + description + "Defines the number of times the underlying link state + has changed to, or from, state up. This counter should be + incremented even if the high layer interface state changes + are being suppressed by a running link flap suppression + timer."; + } + leaf timer-running { + type enumeration { + enum none { + description + "No link flap suppression timer is running."; + } + enum up { + description + "link-flap-suppression up timer is running. The + underlying link state is up, but interface state is + not reported as up."; + } + enum down { + description + "link-flap-suppression down timer is running. + Interface state is reported as up, but the underlying + link state is actually down."; + } + } + config false; + description + "Reports whether a link flap suppression timer is actively + running, in which case the interface state does not match + the underlying link state."; + } + + reference "RFC XXXX, Section 2.1 Link Flap Suppression"; + } + + /* + * Augments the IETF interfaces model with a container to hold + * generic interface dampening + */ + container dampening { + if-feature "dampening"; + presence + "Enable interface link flap dampening with default settings + (that are vendor/device specific)."; + description + "Interface dampening limits the propagation of interface link + state flaps over longer periods."; + reference "RFC XXXX, Section 2.2 Dampening"; + + leaf half-life { + type uint32; + units seconds; + description + "The time (in seconds) after which a penalty would be half + its original value. Once the interface has been assigned + a penalty, the penalty is decreased at a decay rate + equivalent to the half-life. For some devices, the + allowed values may be restricted to particular multiples + of seconds. The default value is vendor/device + specific."; + reference "RFC XXXX, Section 2.3.2 Half-Life Period"; + } + + leaf reuse { + type uint32; + description + "Penalty value below which a stable interface is + unsuppressed (i.e. brought up) (no units). The default + value is vendor/device specific. The penalty value for a + link up->down state change is 1000 units."; + reference "RFC XXXX, Section 2.2.3 Reuse Threshold"; + } + + leaf suppress { + type uint32; + description + "Limit at which an interface is suppressed (i.e. held down) + when its penalty exceeds that limit (no units). The value + must be greater than the reuse threshold. The default + value is vendor/device specific. The penalty value for a + link up->down state change is 1000 units."; + reference "RFC XXXX, Section 2.2.1 Suppress Threshold"; + } + + leaf max-suppress-time { + type uint32; + units seconds; + description + "Maximum time (in seconds) that an interface can be + suppressed before being unsuppressed if no further link + up->down state change penalties have been applied. This + value effectively acts as a ceiling that the penalty value + cannot exceed. The default value is vendor/device + specific."; + reference "RFC XXXX, Section 2.2.4 Maximum Suppress Time"; + } + + leaf penalty { + type uint32; + config false; + description + "The current penalty value for this interface. When the + penalty value exceeds the 'suppress' leaf then the + interface is suppressed (i.e. held down)."; + reference "RFC XXXX, Section 2.2 Dampening"; + } + + leaf suppressed { + type boolean; + config false; + description + "Represents whether the interface is suppressed (i.e. held + down) because the 'penalty' leaf value exceeds the + 'suppress' leaf."; + reference "RFC XXXX, Section 2.2 Dampening"; + } + + leaf time-remaining { + when '../suppressed = "true"' { + description + "Only suppressed interfaces have a time remaining."; + } + type uint32; + units seconds; + config false; + description + "For a suppressed interface, this leaf represents how long + (in seconds) that the interface will remain suppressed + before it is allowed to go back up again."; + reference "RFC XXXX, Section 2.2 Dampening"; + } + } + + /* + * Various types of interfaces support a configurable layer 2 + * encapsulation, any that are supported by YANG should be + * listed here. + * + * Different encapsulations can hook into the common encaps-type + * choice statement. + */ + container encapsulation { + when + "derived-from-or-self(../if:type, + 'ianaift:ethernetCsmacd') or + derived-from-or-self(../if:type, + 'ianaift:ieee8023adLag') or + derived-from-or-self(../if:type, 'ianaift:pos') or + derived-from-or-self(../if:type, + 'ianaift:atmSubInterface') or + derived-from-or-self(../if:type, 'ianaift:l2vlan') or + derived-from-or-self(../if:type, 'ethSubInterface')" { + + description + "All interface types that can have a configurable L2 + encapsulation."; + } + + description + "Holds the OSI layer 2 encapsulation associated with an + interface."; + choice encaps-type { + description + "Extensible choice of layer 2 encapsulations"; + reference "RFC XXXX, Section 2.3 Encapsulation"; + } + } + + /* + * Various types of interfaces support loopback configuration, + * any that are supported by YANG should be listed here. + */ + leaf loopback { + when "derived-from-or-self(../if:type, + 'ianaift:ethernetCsmacd') or + derived-from-or-self(../if:type, 'ianaift:sonet') or + derived-from-or-self(../if:type, 'ianaift:atm') or + derived-from-or-self(../if:type, 'ianaift:otnOtu')" { + description + "All interface types that support loopback configuration."; + } + if-feature "loopback"; + type identityref { + base loopback; + } + description "Enables traffic loopback."; + reference "RFC XXXX, Section 2.4 Loopback"; + } + + /* + * Allows the maximum frame size to be configured or reported. + */ + leaf max-frame-size { + if-feature "max-frame-size"; + type uint32 { + range "64 .. max"; + } + description + "The maximum size of layer 2 frames that may be transmitted + or received on the interface (including any frame header, + maximum frame payload size, and frame checksum sequence). + + If configured, the max-frame-size also limits the maximum + frame size of any child sub-interfaces. The MTU available + to higher layer protocols is restricted to the maximum frame + payload size, and MAY be further restricted by explicit + layer 3 or protocol specific MTU configuration."; + + reference "RFC XXXX, Section 2.5 Maximum Frame Size"; + } + + /* + * Augments the IETF interfaces model with a leaf that indicates + * which mode, or layer, is being used to forward the traffic. + */ + leaf forwarding-mode { + type identityref { + base forwarding-mode; + } + config false; + + description + "The forwarding mode that the interface is operating in."; + reference "RFC XXXX, Section 2.7 Forwarding Mode"; + } + } + + /* + * Add generic support for sub-interfaces. + * + * This should be extended to cover all interface types that are + * child interfaces of other interfaces. + */ + augment "/if:interfaces/if:interface" { + when "derived-from(if:type, 'sub-interface') or + derived-from-or-self(if:type, 'ianaift:l2vlan') or + derived-from-or-self(if:type, 'ianaift:atmSubInterface') or + derived-from-or-self(if:type, 'ianaift:frameRelay')" { + description + "Any ianaift:types that explicitly represent sub-interfaces + or any types that derive from the sub-interface identity."; + } + if-feature "sub-interfaces"; + + description + "Adds a parent interface field to interfaces that model + sub-interfaces."; + leaf parent-interface { + + type if:interface-ref; + + mandatory true; + description + "This is the reference to the parent interface of this + sub-interface."; + reference "RFC XXXX, Section 2.6 Sub-interface"; + } + } + + /* + * Add discard counter for unknown sub-interface encapsulation + */ + augment "/if:interfaces/if:interface/if:statistics" { + when "derived-from-or-self(../if:type, + 'ianaift:ethernetCsmacd') or + derived-from-or-self(../if:type, + 'ianaift:ieee8023adLag') or + derived-from-or-self(../if:type, 'ianaift:ifPwType')" { + description + "Applies to interfaces that can demultiplex ingress frames to + sub-interfaces."; + } + if-feature "sub-interfaces"; + + description + "Augment the interface model statistics with a sub-interface + demux discard counter."; + leaf in-discard-unknown-encaps { + type yang:counter64; + units frames; + description + "A count of the number of frames that were well formed, but + otherwise discarded because their encapsulation does not + classify the frame to the interface or any child + sub-interface. E.g., a frame might be discarded because the + it has an unknown VLAN Id, or does not have a VLAN Id when + one is expected. + + For consistency, frames counted against this counter are + also counted against the IETF interfaces statistics. In + particular, they are included in in-octets and in-discards, + but are not included in in-unicast-pkts, in-multicast-pkts + or in-broadcast-pkts, because they are not delivered to a + higher layer. + + Discontinuities in the values of this counter can occur at + re-initialization of the management system, and at other + times as indicated by the value of the 'discontinuity-time' + leaf defined in the ietf-interfaces YANG module + (RFC 8343)."; + } + } +} diff --git a/holo-yang/modules/ietf/ietf-if-vlan-encapsulation@2023-01-26.yang b/holo-yang/modules/ietf/ietf-if-vlan-encapsulation@2023-01-26.yang new file mode 100644 index 00000000..c49775e4 --- /dev/null +++ b/holo-yang/modules/ietf/ietf-if-vlan-encapsulation@2023-01-26.yang @@ -0,0 +1,155 @@ +module ietf-if-vlan-encapsulation { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-if-vlan-encapsulation"; + prefix if-vlan; + + import ietf-interfaces { + prefix if; + reference + "RFC 8343: A YANG Data Model For Interface Management"; + } + + import iana-if-type { + prefix ianaift; + reference + "RFC 7224: IANA Interface Type YANG Module"; + } + + import ieee802-dot1q-types { + prefix dot1q-types; + revision-date 2022-01-19; + reference + "IEEE Std 802.1Q-2022: IEEE Standard for Local and + metropolitan area networks -- Bridges and Bridged Networks"; + } + + import ietf-if-extensions { + prefix if-ext; + reference + "RFC XXXX: Common Interface Extension YANG Data Models"; + } + + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + + contact + "WG Web: + WG List: + + Editor: Robert Wilton + "; + + description + "This YANG module models configuration to classify IEEE 802.1Q + VLAN tagged Ethernet traffic by exactly matching the tag type + and VLAN identifier of one or two 802.1Q VLAN tags in the frame. + + Copyright (c) 2023 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject to + the license terms contained in, the Revised BSD License set + forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC XXXX + (https://www.rfc-editor.org/info/rfcXXXX); see the RFC itself + for full legal notices. + + The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL + NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED', + 'MAY', and 'OPTIONAL' in this document are to be interpreted as + described in BCP 14 (RFC 2119) (RFC 8174) when, and only when, + they appear in all capitals, as shown here."; + + revision 2023-01-26 { + description + "Latest draft revision"; + reference + "RFC XXXX: Sub-interface VLAN YANG Data Models"; + } + + augment "/if:interfaces/if:interface/if-ext:encapsulation/" + + "if-ext:encaps-type" { + when "derived-from-or-self(../if:type, + 'ianaift:ethernetCsmacd') or + derived-from-or-self(../if:type, + 'ianaift:ieee8023adLag') or + derived-from-or-self(../if:type, 'ianaift:l2vlan') or + derived-from-or-self(../if:type, + 'if-ext:ethSubInterface')" { + description + "Applies only to Ethernet-like interfaces and + sub-interfaces."; + } + + description + "Augment the generic interface encapsulation with basic 802.1Q + VLAN tag classifications"; + + case dot1q-vlan { + container dot1q-vlan { + + description + "Classifies 802.1Q VLAN tagged Ethernet frames to a + sub-interface (or interface) by exactly matching the + number of tags, tag type(s) and VLAN identifier(s). + + Only frames matching the classification configured on a + sub-interface/interface are processed on that + sub-interface/interface. + + Frames that do not match any sub-interface are processed + directly on the parent interface, if it is associated with + a forwarding instance, otherwise they are dropped."; + + container outer-tag { + must 'tag-type = "dot1q-types:s-vlan" or ' + + 'tag-type = "dot1q-types:c-vlan"' { + + error-message + "Only C-VLAN and S-VLAN tags can be matched."; + + description + "For IEEE 802.1Q interoperability, only C-VLAN and + S-VLAN tags are matched."; + } + + description + "Specifies the VLAN tag values to match against the + outermost (first) 802.1Q VLAN tag in the frame."; + + uses dot1q-types:dot1q-tag-classifier-grouping; + } + + container second-tag { + must '../outer-tag/tag-type = "dot1q-types:s-vlan" and ' + + 'tag-type = "dot1q-types:c-vlan"' { + + error-message + "When matching two 802.1Q VLAN tags, the outermost + (first) tag in the frame MUST be specified and be of + S-VLAN type and the second tag in the frame must be of + C-VLAN tag type."; + + description + "For IEEE 802.1Q interoperability, when matching two + 802.1Q VLAN tags, it is REQUIRED that the outermost + tag exists and is an S-VLAN, and the second tag is a + C-VLAN."; + } + + presence "Classify frames that have two 802.1Q VLAN tags."; + + description + "Specifies the VLAN tag values to match against the + second outermost 802.1Q VLAN tag in the frame."; + + uses dot1q-types:dot1q-tag-classifier-grouping; + } + } + } + } +} diff --git a/holo-yang/src/lib.rs b/holo-yang/src/lib.rs index d5e38933..25227378 100644 --- a/holo-yang/src/lib.rs +++ b/holo-yang/src/lib.rs @@ -27,6 +27,9 @@ pub static YANG_CTX: OnceLock> = OnceLock::new(); // default doesn't support loading YANG modules from the filesystem. pub static YANG_EMBEDDED_MODULES: Lazy = Lazy::new(|| { hashmap! { + // IEEE modules + EmbeddedModuleKey::new("ieee802-dot1q-types", Some("2022-01-19"), None, None) => + include_str!("../modules/ieee/ieee802-dot1q-types@2022-01-19.yang"), // IETF modules EmbeddedModuleKey::new("iana-bfd-types", Some("2021-10-21"), None, None) => include_str!("../modules/ietf/iana-bfd-types@2021-10-21.yang"), @@ -70,6 +73,10 @@ pub static YANG_EMBEDDED_MODULES: Lazy = Lazy::new(|| { include_str!("../modules/ietf/ietf-bgp-rib-tables@2023-07-05.yang"), EmbeddedModuleKey::new("ietf-bgp-policy", Some("2023-07-05"), None, None) => include_str!("../modules/ietf/ietf-bgp-policy@2023-07-05.yang"), + EmbeddedModuleKey::new("ietf-if-extensions", Some("2023-01-26"), None, None) => + include_str!("../modules/ietf/ietf-if-extensions@2023-01-26.yang"), + EmbeddedModuleKey::new("ietf-if-vlan-encapsulation", Some("2023-01-26"), None, None) => + include_str!("../modules/ietf/ietf-if-vlan-encapsulation@2023-01-26.yang"), EmbeddedModuleKey::new("ietf-interfaces", Some("2018-02-20"), None, None) => include_str!("../modules/ietf/ietf-interfaces@2018-02-20.yang"), EmbeddedModuleKey::new("ietf-ip", Some("2018-02-22"), None, None) => @@ -126,6 +133,10 @@ pub static YANG_EMBEDDED_MODULES: Lazy = Lazy::new(|| { include_str!("../modules/deviations/ietf-bgp-holo-deviations.yang"), EmbeddedModuleKey::new("ietf-mpls-ldp-holo-deviations", None, None, None) => include_str!("../modules/deviations/ietf-mpls-ldp-holo-deviations.yang"), + EmbeddedModuleKey::new("ietf-if-extensions-holo-deviations", None, None, None) => + include_str!("../modules/deviations/ietf-if-extensions-holo-deviations.yang"), + EmbeddedModuleKey::new("ietf-if-vlan-encapsulation-holo-deviations", None, None, None) => + include_str!("../modules/deviations/ietf-if-vlan-encapsulation-holo-deviations.yang"), EmbeddedModuleKey::new("ietf-interfaces-holo-deviations", None, None, None) => include_str!("../modules/deviations/ietf-interfaces-holo-deviations.yang"), EmbeddedModuleKey::new("ietf-ip-holo-deviations", None, None, None) => @@ -160,6 +171,9 @@ pub static YANG_EMBEDDED_MODULES: Lazy = Lazy::new(|| { pub static YANG_IMPLEMENTED_MODULES: Lazy> = Lazy::new(|| { vec![ + // IEEE modules + "ieee802-dot1q-types", + // IETF modules "iana-if-type", "iana-bgp-notification", "iana-bgp-rib-types", @@ -171,6 +185,8 @@ pub static YANG_IMPLEMENTED_MODULES: Lazy> = "ietf-bgp", "ietf-bgp-policy", "ietf-routing-types", + "ietf-if-extensions", + "ietf-if-vlan-encapsulation", "ietf-interfaces", "ietf-ip", "ietf-key-chain", @@ -188,6 +204,7 @@ pub static YANG_IMPLEMENTED_MODULES: Lazy> = "ietf-ospfv3-extended-lsa", "ietf-rip", "ietf-tcp", + // IETF Holo augmentations "holo-bgp", "holo-ospf", "holo-ospf-dev", @@ -210,6 +227,9 @@ pub static YANG_FEATURES: Lazy>> = "hex-key-string", "independent-send-accept-lifetime", ], + "ietf-if-extensions" => vec![ + "sub-interfaces", + ], "ietf-ospf" => vec![ "bfd", "explicit-router-id",