Extend LLDP model with global TTL, custom TLV, and per-interface enhancements#1470
Extend LLDP model with global TTL, custom TLV, and per-interface enhancements#1470ndas7 wants to merge 4 commits intoopenconfig:masterfrom
Conversation
…ncements ### Change Scope * This PR proposes enhancements to the existing LLDP model with the following changes: 1. Adding a global ttl configuration/state leaf under /lldp. 2. Extending interface LLDP config and state with port-description and interface-level custom-tlv-names. 3. Introducing a shared custom-TLV grouping so both config and state reuse the same custom TLV fields. 4. Adding a top-level /lldp/custom-tlvs/tlv[name] list for global custom TLV definitions. 5. Adding interface state timestamp counters for LLDP packet events. ### Platform Implementations * LLDPCLI, LLDPAD (LLDP daemons for Linux): https://lldpd.github.io/usage.html ``` lldpcli configure lldp custom-tlv oui 00,00,00 subtype 1 oui-info "your data" ``` * SONiC: https://github.com/cshivashgit/SONiC/blob/lldp-custom-tlv-hld/doc/lldp_custom_tlv/lldp-custom-tlv-hld.md#config-db-schema * Vendors use custom TLVs to support features like Cisco's [LLDP-MED](https://www.cisco.com/c/en/us/td/docs/switches/lan/catalyst9300/software/release/16-6/configuration_guide/int_and_hw/b_166_int_and_hw_9300_cg/b_166_int_and_hw_9300_cg_chapter_011.html) (Media Endpoint Discovery), which is itself a collection of organizationally specific TLVs. In Cisco [NX-OS](https://www.cisco.com/c/en/us/td/docs/switches/datacenter/nexus9000/sw/6-x/system_management/configuration/guide/b_Cisco_Nexus_9000_Series_NX-OS_System_Management_Configuration_Guide/sm_lldp.pdf), you can select which TLVs to include using the lldp tlv-select command. Aruba's [AOS-CX](https://www.youtube.com/watch?v=lPbtpFcTqgE) introduced a specific OUI (83A30) to help identify Aruba devices and automatically apply network profiles. ### Tree View ```diff module: openconfig-lldp +--rw lldp +--rw config | +--rw enabled? boolean | +--rw hello-timer? uint64 + | +--rw ttl? uint64 | +--rw suppress-tlv-advertisement* identityref | +--rw system-name? string | +--rw system-description? string | +--rw chassis-id? string | +--rw chassis-id-type? oc-lldp-types:chassis-id-type | +--rw management-interface? oc-if:interface-id +--ro state | +--ro enabled? boolean | +--ro hello-timer? uint64 + | +--ro ttl? uint64 | +--ro suppress-tlv-advertisement* identityref | +--ro system-name? string | +--ro system-description? string | +--ro chassis-id? string | +--ro chassis-id-type? oc-lldp-types:chassis-id-type | +--ro management-interface? oc-if:interface-id | +--ro counters | +--ro frame-in? oc-yang:counter64 | +--ro frame-out? oc-yang:counter64 | +--ro frame-error-in? oc-yang:counter64 | +--ro frame-discard? oc-yang:counter64 | +--ro tlv-discard? oc-yang:counter64 | +--ro tlv-unknown? oc-yang:counter64 | +--ro last-clear? oc-yang:date-and-time | +--ro tlv-accepted? oc-yang:counter64 | +--ro entries-aged-out? oc-yang:counter64 +--ro mgmt-addresses | +--ro mgmt-address* [address] | +--ro address -> ../state/address | +--ro state | +--ro address? union | +--ro interface-number? uint32 | +--ro interface-number-subtype? oc-lldp-types:mgmt-interface-number-subtype +--rw interfaces | +--rw interface* [name] | +--rw name -> ../config/name | +--rw config | | +--rw name? oc-if:base-interface-ref | | +--rw enabled? boolean + | | +--rw port-description? string + | | +--rw custom-tlv-names* -> ../../../../custom-tlvs/tlv/name | +--ro state | | +--ro name? oc-if:base-interface-ref | | +--ro enabled? boolean + | | +--ro port-description? string + | | +--ro custom-tlv-names* -> ../../../../custom-tlvs/tlv/name | | +--ro counters | | +--ro frame-in? oc-yang:counter64 | | +--ro frame-out? oc-yang:counter64 | | +--ro frame-error-in? oc-yang:counter64 | | +--ro frame-discard? oc-yang:counter64 | | +--ro tlv-discard? oc-yang:counter64 | | +--ro tlv-unknown? oc-yang:counter64 | | +--ro last-clear? oc-yang:date-and-time | | +--ro frame-error-out? oc-yang:counter64 + | | +--ro last-packet-transmitted? oc-yang:date-and-time + | | +--ro last-good-packet-received? oc-yang:date-and-time + | | +--ro loopback-packets-received? oc-yang:date-and-time | +--ro neighbors | +--ro neighbor* [id] | +--ro id -> ../state/id | +--ro config | +--ro state | | +--ro system-name? string | | +--ro system-description? string | | +--ro chassis-id? string | | +--ro chassis-id-type? oc-lldp-types:chassis-id-type | | +--ro management-interface? oc-if:interface-id | | +--ro id? string | | +--ro age? uint64 | | +--ro last-update? int64 | | +--ro ttl? uint16 | | +--ro port-id? string | | +--ro port-id-type? oc-lldp-types:port-id-type | | +--ro port-description? string | | x--ro management-address? string | | x--ro management-address-type? string | +--ro mgmt-addresses | | +--ro mgmt-address* [address] | | +--ro address -> ../state/address | | +--ro state | | +--ro address? union | | +--ro interface-number? uint32 | | +--ro interface-number-subtype? oc-lldp-types:mgmt-interface-number-subtype | +--ro custom-tlvs | | +--ro tlv* [type oui oui-subtype] | | +--ro type -> ../state/type | | +--ro oui -> ../state/oui | | +--ro oui-subtype -> ../state/oui-subtype | | +--ro config | | +--ro state + | | +--ro name? string | | +--ro type? int32 | | +--ro oui? string | | +--ro oui-subtype? string | | +--ro value? binary | +--ro capabilities | +--ro capability* [name] | +--ro name -> ../state/name | +--ro config | +--ro state | +--ro name? identityref | +--ro enabled? boolean + +--rw custom-tlvs + +--rw tlv* [name] + +--rw name -> ../config/name + +--rw config + | +--rw name? string + | +--rw type? int32 + | +--rw oui? string + | +--rw oui-subtype? string + | +--rw value? binary + +--ro state + +--ro name? string + +--ro type? int32 + +--ro oui? string + +--ro oui-subtype? string + +--ro value? binary ``` Signed-off-by: Neha Das <neha.das43@gmail.com>
There was a problem hiding this comment.
Code Review
This pull request updates the OpenConfig LLDP module to version 1.0.1, introducing global TTL configuration, interface-level port descriptions, and timestamps for packet transmission and reception. It also adds a global custom TLV list and allows interfaces to reference these TLVs. Review feedback recommends renaming the loopback packet timestamp for consistency, correcting the description of the port-description leaf to reflect the correct TLV type, and changing the TTL data type from uint64 to uint16 to align with the IEEE 802.1AB standard.
Signed-off-by: Neha Das <neha.das43@gmail.com>
Signed-off-by: Neha Das <neha.das43@gmail.com>
| for the LLDP protocol."; | ||
|
|
||
| oc-ext:openconfig-version "1.0.0"; | ||
| oc-ext:openconfig-version "1.0.1"; |
There was a problem hiding this comment.
| oc-ext:openconfig-version "1.0.1"; | |
| oc-ext:openconfig-version "1.1.0"; |
| } | ||
|
|
||
| leaf last-packet-transmitted { | ||
| type oc-yang:date-and-time; |
There was a problem hiding this comment.
| type oc-yang:date-and-time; | |
| type oc-types:timeticks64; |
I know there is already a leaf w/ oc-yang:date-and-time here but imo this was incorrect per common and more programmatic friendly representation of time since unix epoch
| } | ||
|
|
||
| leaf last-good-packet-received { | ||
| type oc-yang:date-and-time; |
There was a problem hiding this comment.
Same as above although I would question more non-counter leafs under this counters container. Seems appropriate to move these up to a parent level
| "Enable or disable the LLDP protocol on the interface."; | ||
| } | ||
|
|
||
| leaf port-description { |
There was a problem hiding this comment.
I think some clarification would need to surround this leaf as most implementations would derive this TLV from other areas (e.g. interface description) by default and your intention here appears to be a TLV specific override
| "System level hello timer for the LLDP protocol."; | ||
| } | ||
|
|
||
| leaf ttl { |
There was a problem hiding this comment.
How will this field conflict or relate to hello-timer for where in implementations this is derived/calculated?
| } | ||
|
|
||
| leaf type { | ||
| type int32; |
There was a problem hiding this comment.
I know you are just reusing what was previously defined but this is an incorrect type for what is a 7-bit unsigned field per spec definition.
Suggest proposing/refactoring to a scoped uint8 to go in accordance to 8021AB-2016
| } | ||
|
|
||
| leaf oui { | ||
| type string; |
There was a problem hiding this comment.
Would suggest considering typedef w/ constraints for these fields
| } | ||
|
|
||
| leaf oui-subtype { | ||
| type string; |
There was a problem hiding this comment.
Would suggest considering typedef w/ constraints for these fields
| unique subtype value assigned by the defining organization."; | ||
| } | ||
|
|
||
| // TODO: consider making this string type |
There was a problem hiding this comment.
Since you are proposing the ability for r/w in here, this probably should be revisited. If we maintain type binary this complicates the reading/writing for users
| path "../../../../custom-tlvs/tlv/name"; | ||
| } | ||
| description | ||
| "References to global custom TLV names associated with this interface."; |
There was a problem hiding this comment.
Suggest being very specific here and state something like, if present in the list, the tlv is advertised and if not, the tlv will not be advertised
| "The description of the port to be advertised in the Port | ||
| Description TLV (Type 4) for LLDP PDUs transmitted on this | ||
| interface."; | ||
| } |
There was a problem hiding this comment.
I would expect that implementations today would use this leaf as the LLDP port-description.
/interfaces/interface/state/description
Discussing this, the desire is to override the interface description with an LLDP specific string. Please update the description to indicate what happens if this leaf is not populated and if it is. Thanks!
| leaf name { | ||
| type string; | ||
| description | ||
| "Name of the custom TLV."; |
There was a problem hiding this comment.
Please elaborate that this is for ease for human identification of the LLDP type.
|
/gcbrun |
|
No major YANG version changes in commit f1bd4f0 |
Change Scope
* This PR proposes enhancements to the existing LLDP model with the following changes:
1. Adding a global ttl configuration/state leaf under /lldp.
2. Extending interface LLDP config and state with port-description and interface-level custom-tlv-names.
3. Introducing a shared custom-TLV grouping so both config and state reuse the same custom TLV fields.
4. Adding a top-level /lldp/custom-tlvs/tlv[name] list for global custom TLV definitions.
5. Adding interface state timestamp counters for LLDP packet events.
Platform Implementations
* LLDPCLI, LLDPAD (LLDP daemons for Linux): https://lldpd.github.io/usage.html
* SONiC: https://github.com/cshivashgit/SONiC/blob/lldp-custom-tlv-hld/doc/lldp_custom_tlv/lldp-custom-tlv-hld.md#config-db-schema
* Vendors use custom TLVs to support features like Cisco's LLDP-MED (Media Endpoint Discovery), which is itself a collection of organizationally specific TLVs. In Cisco NX-OS, you can select which TLVs to include using the lldp tlv-select command. Aruba's AOS-CX introduced a specific OUI (83A30) to help identify Aruba devices and automatically apply network profiles.
Tree View
module: openconfig-lldp +--rw lldp +--rw config | +--rw enabled? boolean | +--rw hello-timer? uint64 + | +--rw ttl? uint16 | +--rw suppress-tlv-advertisement* identityref | +--rw system-name? string | +--rw system-description? string | +--rw chassis-id? string | +--rw chassis-id-type? oc-lldp-types:chassis-id-type | +--rw management-interface? oc-if:interface-id +--ro state | +--ro enabled? boolean | +--ro hello-timer? uint64 + | +--ro ttl? uint16 | +--ro suppress-tlv-advertisement* identityref | +--ro system-name? string | +--ro system-description? string | +--ro chassis-id? string | +--ro chassis-id-type? oc-lldp-types:chassis-id-type | +--ro management-interface? oc-if:interface-id | +--ro counters | +--ro frame-in? oc-yang:counter64 | +--ro frame-out? oc-yang:counter64 | +--ro frame-error-in? oc-yang:counter64 | +--ro frame-discard? oc-yang:counter64 | +--ro tlv-discard? oc-yang:counter64 | +--ro tlv-unknown? oc-yang:counter64 | +--ro last-clear? oc-yang:date-and-time | +--ro tlv-accepted? oc-yang:counter64 | +--ro entries-aged-out? oc-yang:counter64 +--ro mgmt-addresses | +--ro mgmt-address* [address] | +--ro address -> ../state/address | +--ro state | +--ro address? union | +--ro interface-number? uint32 | +--ro interface-number-subtype? oc-lldp-types:mgmt-interface-number-subtype +--rw interfaces | +--rw interface* [name] | +--rw name -> ../config/name | +--rw config | | +--rw name? oc-if:base-interface-ref | | +--rw enabled? boolean + | | +--rw port-description? string + | | +--rw custom-tlv-names* -> ../../../../custom-tlvs/tlv/name | +--ro state | | +--ro name? oc-if:base-interface-ref | | +--ro enabled? boolean + | | +--ro port-description? string + | | +--ro custom-tlv-names* -> ../../../../custom-tlvs/tlv/name | | +--ro counters | | +--ro frame-in? oc-yang:counter64 | | +--ro frame-out? oc-yang:counter64 | | +--ro frame-error-in? oc-yang:counter64 | | +--ro frame-discard? oc-yang:counter64 | | +--ro tlv-discard? oc-yang:counter64 | | +--ro tlv-unknown? oc-yang:counter64 | | +--ro last-clear? oc-yang:date-and-time | | +--ro frame-error-out? oc-yang:counter64 + | | +--ro last-packet-transmitted? oc-yang:date-and-time + | | +--ro last-good-packet-received? oc-yang:date-and-time + | | +--ro loopback-packets-received? oc-yang:counter64 | +--ro neighbors | +--ro neighbor* [id] | +--ro id -> ../state/id | +--ro config | +--ro state | | +--ro system-name? string | | +--ro system-description? string | | +--ro chassis-id? string | | +--ro chassis-id-type? oc-lldp-types:chassis-id-type | | +--ro management-interface? oc-if:interface-id | | +--ro id? string | | +--ro age? uint64 | | +--ro last-update? int64 | | +--ro ttl? uint16 | | +--ro port-id? string | | +--ro port-id-type? oc-lldp-types:port-id-type | | +--ro port-description? string | | x--ro management-address? string | | x--ro management-address-type? string | +--ro mgmt-addresses | | +--ro mgmt-address* [address] | | +--ro address -> ../state/address | | +--ro state | | +--ro address? union | | +--ro interface-number? uint32 | | +--ro interface-number-subtype? oc-lldp-types:mgmt-interface-number-subtype | +--ro custom-tlvs | | +--ro tlv* [type oui oui-subtype] | | +--ro type -> ../state/type | | +--ro oui -> ../state/oui | | +--ro oui-subtype -> ../state/oui-subtype | | +--ro config | | +--ro state + | | +--ro name? string | | +--ro type? int32 | | +--ro oui? string | | +--ro oui-subtype? string | | +--ro value? binary | +--ro capabilities | +--ro capability* [name] | +--ro name -> ../state/name | +--ro config | +--ro state | +--ro name? identityref | +--ro enabled? boolean + +--rw custom-tlvs + +--rw tlv* [name] + +--rw name -> ../config/name + +--rw config + | +--rw name? string + | +--rw type? int32 + | +--rw oui? string + | +--rw oui-subtype? string + | +--rw value? binary + +--ro state + +--ro name? string + +--ro type? int32 + +--ro oui? string + +--ro oui-subtype? string + +--ro value? binary