Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor physical ethernet vs. aggregate interface characteristics #1183

Merged
merged 10 commits into from
Oct 31, 2024

Conversation

earies
Copy link
Contributor

@earies earies commented Sep 17, 2024

  • (M) release/models/interfaces/openconfig-if-ethernet.yang
    • Split/restrict physical vs. aggregate ethernet config/state

Change Scope

Per #1181 it was pointed out that
the reuse of all ethernet characteristics for both physical and aggregate
interfaces does not provide guidance or restrictions of what and how to
populate/certain leafs depending on the interface type.

This PR divides up groupings into physical and common data nodes gating what is
supported based on the interface type.

Validated instance-data below per the new restrictions:

{
  "openconfig-interfaces:interfaces": {
    "interface": [
      {
        "name": "ae0",
        "config": {
          "name": "ae0",
          "type": "iana-if-type:ieee8023adLag"
        },
        "state": {
          "name": "ae0",
          "type": "iana-if-type:ieee8023adLag",
          "loopback-mode": "NONE",
          "enabled": true,
          "admin-status": "UP",
          "oper-status": "UP"
        },
        "hold-time": {
          "state": {
            "up": 0,
            "down": 0
          }
        },
        "penalty-based-aied": {
          "state": {
            "max-suppress-time": 0,
            "decay-half-life": 0,
            "suppress-threshold": 0,
            "reuse-threshold": 0,
            "flap-penalty": 0
          }
        },
        "openconfig-if-aggregate:aggregation": {
          "config": {
            "lag-type": "LACP",
            "min-links": 1
          },
          "state": {
            "lag-type": "LACP",
            "min-links": 1,
            "lag-speed": 800000
          }
        },
        "openconfig-if-ethernet:ethernet": {
          "config": {
            "mac-address": "00:00:00:00:00:1a",
            "enable-flow-control": true
          },
          "state": {
            "mac-address": "00:00:00:00:00:1a",
            "enable-flow-control": true
          }
        }
      },
      {
        "name": "et-0/0/0",
        "config": {
          "name": "et-0/0/0",
          "type": "iana-if-type:ethernetCsmacd"
        },
        "state": {
          "name": "et-0/0/0",
          "type": "iana-if-type:ethernetCsmacd",
          "loopback-mode": "NONE",
          "enabled": true,
          "admin-status": "UP",
          "oper-status": "UP"
        },
        "hold-time": {
          "state": {
            "up": 0,
            "down": 0
          }
        },
        "penalty-based-aied": {
          "state": {
            "max-suppress-time": 0,
            "decay-half-life": 0,
            "suppress-threshold": 0,
            "reuse-threshold": 0,
            "flap-penalty": 0
          }
        },
        "openconfig-if-ethernet:ethernet": {
          "config": {
            "mac-address": "00:00:00:00:00:aa",
            "enable-flow-control": true,
            "auto-negotiate": true,
            "duplex-mode": "FULL",
            "port-speed": "SPEED_400GB",
            "openconfig-if-aggregate:aggregate-id": "ae0"
          },
          "state": {
            "mac-address": "00:00:00:00:00:aa",
            "enable-flow-control": true,
            "auto-negotiate": true,
            "standalone-link-training": false,
            "duplex-mode": "FULL",
            "port-speed": "SPEED_400GB",
            "hw-mac-address": "ff:00:00:00:00:01",
            "negotiated-duplex-mode": "FULL",
            "negotiated-port-speed": "SPEED_400GB",
            "openconfig-if-aggregate:aggregate-id": "ae0"
          }
        }
      },
      {
        "name": "et-0/0/1",
        "config": {
          "name": "et-0/0/1",
          "type": "iana-if-type:ethernetCsmacd"
        },
        "state": {
          "name": "et-0/0/1",
          "type": "iana-if-type:ethernetCsmacd",
          "loopback-mode": "NONE",
          "enabled": true,
          "admin-status": "UP",
          "oper-status": "UP"
        },
        "hold-time": {
          "state": {
            "up": 0,
            "down": 0
          }
        },
        "penalty-based-aied": {
          "state": {
            "max-suppress-time": 0,
            "decay-half-life": 0,
            "suppress-threshold": 0,
            "reuse-threshold": 0,
            "flap-penalty": 0
          }
        },
        "openconfig-if-ethernet:ethernet": {
          "config": {
            "mac-address": "00:00:00:00:00:ab",
            "enable-flow-control": true,
            "auto-negotiate": true,
            "duplex-mode": "FULL",
            "port-speed": "SPEED_400GB",
            "openconfig-if-aggregate:aggregate-id": "ae0"
          },
          "state": {
            "mac-address": "00:00:00:00:00:ab",
            "enable-flow-control": true,
            "auto-negotiate": true,
            "standalone-link-training": false,
            "duplex-mode": "FULL",
            "port-speed": "SPEED_400GB",
            "hw-mac-address": "ff:00:00:00:00:02",
            "negotiated-duplex-mode": "FULL",
            "negotiated-port-speed": "SPEED_400GB",
            "openconfig-if-aggregate:aggregate-id": "ae0"
          }
        }
      }
    ]
  }
}

Failure cases

If an aggregate interface contains port-speed

libyang err : When condition "../../oc-if:config/oc-if:type = 'ianaift:ethernetCsmacd'" not satisfied. (/openconfig-interfaces:interfaces/interface[name='ae0']/openconfig-if-ethernet:ethernet/state/port-speed)

The correct leaf node to report is rather aggregation/state/lag-speed

If an aggregate interface contains negotiated-port-speed

libyang err : When condition "../../oc-if:config/oc-if:type = 'ianaift:ethernetCsmacd'" not satisfied. (/openconfig-interfaces:interfaces/interface[name='ae0']/openconfig-if-ethernet:ethernet/state/negotiated-port-speed)

... and similar for physical interface characteristics under a logical interface of non ethernetCsmacd type

Platform Implementations

Bug fix & enforced restrictions

Edit: 2024-10-07

Due to reuse of this model within wifi related models, when restrictions are severely restricted at this time. This PR has been refactored to segment out groupings and update description statements to describe the behavior until otherwise resolved.

Edit: 2024-10-31

Updated tree view (w/ groupings) per comment #1183 (comment)

module: openconfig-interfaces
  +--rw interfaces
     +--rw interface* [name]
        +--rw oc-eth:ethernet
           +--rw oc-eth:config
           |  +--rw oc-eth:mac-address?                oc-yang:mac-address
           |  +--rw oc-eth:enable-flow-control?        boolean
           |  +--rw oc-eth:auto-negotiate?             boolean
           |  +--rw oc-eth:standalone-link-training?   boolean
           |  +--rw oc-eth:duplex-mode?                enumeration
           |  +--rw oc-eth:port-speed?                 identityref
           |  +--rw oc-eth:fec-mode?                   identityref
           |  +--rw oc-lag:aggregate-id?               -> /oc-if:interfaces/interface/name
           +--ro oc-eth:state
              +--ro oc-eth:mac-address?                oc-yang:mac-address
              +--ro oc-eth:enable-flow-control?        boolean
              +--ro oc-eth:auto-negotiate?             boolean
              +--ro oc-eth:standalone-link-training?   boolean
              +--ro oc-eth:duplex-mode?                enumeration
              +--ro oc-eth:port-speed?                 identityref
              +--ro oc-eth:fec-mode?                   identityref
              +--ro oc-eth:hw-mac-address?             oc-yang:mac-address
              +--ro oc-eth:negotiated-duplex-mode?     enumeration
              +--ro oc-eth:negotiated-port-speed?      identityref
              +--ro oc-eth:counters
              |  +--ro oc-eth:in-mac-control-frames?    oc-yang:counter64
              |  +--ro oc-eth:in-mac-pause-frames?      oc-yang:counter64
              |  +--ro oc-eth:in-oversize-frames?       oc-yang:counter64
              |  +--ro oc-eth:in-undersize-frames?      oc-yang:counter64
              |  +--ro oc-eth:in-jabber-frames?         oc-yang:counter64
              |  +--ro oc-eth:in-fragment-frames?       oc-yang:counter64
              |  +--ro oc-eth:in-8021q-frames?          oc-yang:counter64
              |  +--ro oc-eth:in-crc-errors?            oc-yang:counter64
              |  +--ro oc-eth:in-block-errors?          oc-yang:counter64
              |  +--ro oc-eth:in-carrier-errors?        oc-yang:counter64
              |  +--ro oc-eth:in-interrupted-tx?        oc-yang:counter64
              |  +--ro oc-eth:in-late-collision?        oc-yang:counter64
              |  +--ro oc-eth:in-mac-errors-rx?         oc-yang:counter64
              |  +--ro oc-eth:in-single-collision?      oc-yang:counter64
              |  +--ro oc-eth:in-symbol-error?          oc-yang:counter64
              |  +--ro oc-eth:in-maxsize-exceeded?      oc-yang:counter64
              |  +--ro oc-eth:out-mac-control-frames?   oc-yang:counter64
              |  +--ro oc-eth:out-mac-pause-frames?     oc-yang:counter64
              |  +--ro oc-eth:out-8021q-frames?         oc-yang:counter64
              |  +--ro oc-eth:out-mac-errors-tx?        oc-yang:counter64
              +--ro oc-lag:aggregate-id?               -> /oc-if:interfaces/interface/name

  grouping interface-ref-common:
    +-- interface?      -> /interfaces/interface/name
    +-- subinterface?   -> /interfaces/interface[oc-if:name=current()/../interface]/subinterfaces/subinterface/index
  grouping interface-ref-state-container:
    +--ro state
  grouping interface-ref:
    +-- interface-ref
  grouping interface-ref-state:
    +-- interface-ref
  grouping base-interface-ref-state:
    +--ro state
  grouping interface-common-config:
    +-- description?   string
    +-- enabled?       boolean
  grouping interface-phys-config:
    +-- name?            string
    +-- type             identityref
    +-- mtu?             uint16
    +-- loopback-mode?   oc-opt-types:loopback-mode-type
    +-- description?     string
    +-- enabled?         boolean
  grouping interface-phys-holdtime-config:
    +-- up?     uint32
    +-- down?   uint32
  grouping interface-phys-holdtime-state:
  grouping interface-phys-holdtime-top:
    +-- hold-time
  grouping interface-link-damping-config:
    +-- max-suppress-time?    uint32
    +-- decay-half-life?      uint32
    +-- suppress-threshold?   uint32
    +-- reuse-threshold?      uint32
    +-- flap-penalty?         uint32
  grouping interface-link-damping-state:
  grouping link-damping-top:
    +-- penalty-based-aied
  grouping interface-common-state:
    +-- ifindex?        uint32
    +-- admin-status    enumeration
    +-- oper-status     enumeration
    +-- last-change?    oc-types:timeticks64
    +-- logical?        boolean
    +-- management?     boolean
    +-- cpu?            boolean
  grouping interface-common-counters-state:
    +-- in-octets?            oc-yang:counter64
    +-- in-pkts?              oc-yang:counter64
    +-- in-unicast-pkts?      oc-yang:counter64
    +-- in-broadcast-pkts?    oc-yang:counter64
    +-- in-multicast-pkts?    oc-yang:counter64
    +-- in-errors?            oc-yang:counter64
    +-- in-discards?          oc-yang:counter64
    +-- out-octets?           oc-yang:counter64
    +-- out-pkts?             oc-yang:counter64
    +-- out-unicast-pkts?     oc-yang:counter64
    +-- out-broadcast-pkts?   oc-yang:counter64
    +-- out-multicast-pkts?   oc-yang:counter64
    +-- out-discards?         oc-yang:counter64
    +-- out-errors?           oc-yang:counter64
    +-- last-clear?           oc-types:timeticks64
  grouping interface-counters-state:
    +-- in-unknown-protos?     oc-yang:counter64
    +-- in-fcs-errors?         oc-yang:counter64
    +-- carrier-transitions?   oc-yang:counter64
    +-- resets?                oc-yang:counter64
  grouping subinterfaces-counters-state:
    x-- in-unknown-protos?     oc-yang:counter64
    x-- in-fcs-errors?         oc-yang:counter64
    x-- carrier-transitions?   oc-yang:counter64
  grouping sub-unnumbered-config:
    +-- enabled?   boolean
  grouping sub-unnumbered-state:
  grouping sub-unnumbered-top:
    +-- unnumbered
  grouping subinterfaces-config:
    +-- index?         uint32
    +-- description?   string
    +-- enabled?       boolean
  grouping subinterfaces-state:
    +-- name?           string
    +-- ifindex?        uint32
    +-- admin-status    enumeration
    +-- oper-status     enumeration
    +-- last-change?    oc-types:timeticks64
    +-- logical?        boolean
    +-- management?     boolean
    +-- cpu?            boolean
    +-- counters
  grouping subinterfaces-top:
    +-- subinterfaces
  grouping interfaces-top:
    +-- interfaces

module: openconfig-if-aggregate

  grouping aggregation-logical-config:
    +-- lag-type?    aggregation-type
    +-- min-links?   uint16
  grouping aggregation-logical-state:
    +-- lag-speed?   uint32
    +-- member*      oc-if:base-interface-ref
  grouping aggregation-logical-top:
    +-- aggregation
  grouping ethernet-if-aggregation-config:
    +-- aggregate-id?   -> /oc-if:interfaces/interface/name

module: openconfig-if-ethernet

  grouping ethernet-interface-config:
    +-- mac-address?           oc-yang:mac-address
    +-- enable-flow-control?   boolean
  grouping physical-interface-config:
    +-- auto-negotiate?             boolean
    +-- standalone-link-training?   boolean
    +-- duplex-mode?                enumeration
    +-- port-speed?                 identityref
    +-- fec-mode?                   identityref
  grouping ethernet-interface-state-counters:
    +-- in-mac-control-frames?    oc-yang:counter64
    +-- in-mac-pause-frames?      oc-yang:counter64
    +-- in-oversize-frames?       oc-yang:counter64
    +-- in-undersize-frames?      oc-yang:counter64
    +-- in-jabber-frames?         oc-yang:counter64
    +-- in-fragment-frames?       oc-yang:counter64
    +-- in-8021q-frames?          oc-yang:counter64
    +-- in-crc-errors?            oc-yang:counter64
    +-- in-block-errors?          oc-yang:counter64
    +-- in-carrier-errors?        oc-yang:counter64
    +-- in-interrupted-tx?        oc-yang:counter64
    +-- in-late-collision?        oc-yang:counter64
    +-- in-mac-errors-rx?         oc-yang:counter64
    +-- in-single-collision?      oc-yang:counter64
    +-- in-symbol-error?          oc-yang:counter64
    +-- in-maxsize-exceeded?      oc-yang:counter64
    +-- out-mac-control-frames?   oc-yang:counter64
    +-- out-mac-pause-frames?     oc-yang:counter64
    +-- out-8021q-frames?         oc-yang:counter64
    +-- out-mac-errors-tx?        oc-yang:counter64
  grouping physical-interface-state:
    +-- hw-mac-address?           oc-yang:mac-address
    +-- negotiated-duplex-mode?   enumeration
    +-- negotiated-port-speed?    identityref
  grouping ethernet-interface-state:
    +-- counters
  grouping ethernet-top:
    +-- ethernet

  * (M) release/models/interfaces/openconfig-if-ethernet.yang
    - Split/restrict physical vs. aggregate ethernet config/state
@cfyo
Copy link
Contributor

cfyo commented Sep 17, 2024

This looks good to me and also removes the other leaves that aren't really valid for the aggregated interface. Thanks!

@dplore
Copy link
Member

dplore commented Sep 18, 2024

/gcbrun

@OpenConfigBot
Copy link

OpenConfigBot commented Sep 18, 2024

No major YANG version changes in commit 1880fdf

@dplore
Copy link
Member

dplore commented Sep 18, 2024

Adding a backwards compatibility note. As currently proposed, a client / management system must know the type of interface in order to access the speed of the interface. (ie: physical vs. logical).

Would it be better to have a new "speed" leaf which is uint32 in Mbps that is generic across physical and logical interfaces? This could be introduced as a non-breaking change and would be easier to consume.

How important is it to use an identity for the speed of a physical port?

@earies
Copy link
Contributor Author

earies commented Sep 18, 2024

Adding a backwards compatibility note. As currently proposed, a client / management system must know the type of interface in order to access the speed of the interface. (ie: physical vs. logical).

Would it be better to have a new "speed" leaf which is uint32 in Mbps that is generic across physical and logical interfaces? This could be introduced as a non-breaking change and would be easier to consume.

How important is it to use an identity for the speed of a physical port?

The identity (or enum) approach is helpful for a finite set of values especially when configuring between an choice. Having this as a unbound uint32 will require implementations to dictate the format/matrix of what is acceptable vs. not and have more checks in place as to what to accept.

But it would represent a single leaf at a common location no matter the type however some interface types may not have a notion of "speed" still

For reference from ietf-interfaces for a r/o state node only:

      leaf speed {
        type yang:gauge64;
        units "bits/second";
        config false;
        description
            "An estimate of the interface's current bandwidth in bits
             per second.  For interfaces that do not vary in
             bandwidth or for those where no accurate estimation can
             be made, this node should contain the nominal bandwidth.
             For interfaces that have no concept of bandwidth, this
             node is not present.";
        reference
          "RFC 2863: The Interfaces Group MIB -
                     ifSpeed, ifHighSpeed";
      }

This patch set also differentiates more than just "speed" and more about physical vs. logical

@cfyo
Copy link
Contributor

cfyo commented Sep 23, 2024

The lag-speed under /interfaces/interface/aggregation/state
Reports effective speed of the aggregate interface, based on speed of active member interfaces
so do we need another speed leaf for it?

@LimeHat
Copy link

LimeHat commented Sep 23, 2024

Would it be better to have a new "speed" leaf which is uint32 in Mbps that is generic across physical and logical interfaces? This could be introduced as a non-breaking change and would be easier to consume.

I would say no, it will not be better.

First, the current ethernet interface speed is RW (can be configured). In some cases the speed is auto-derived, but that's not necessarily true. And the config have to be restricted to the IEEE defined ethernet speeds (one way or another).

Secondly, is there a real use case for the consumption of interface speeds by a controller that is not aware of what type of interface it uses? And to add to that, that controller cannot subscribe to two sets of leaves and has to consume it from the single one? That feels like a bit of a stretch.

Last but not least, I would disagree with the notion of introduced as a non-breaking change.
The way "non-breaking" is defined in OpenConfig community is very limited and doesn't take into the account the real world usage of the models.

The current leaves are well defined and been present in the models for almost 10 years, and there are a significant number of implementations. Introducing a new leaf that is going to replace the two old ones is actually will be non-backward compatible for all these implementations (client software will have to be updated first and support the consumption of two sets of leaves, until all NOS systems are fully migrated to the new model; and make a decision which one to consume based on a specific NOS version/capabilities advertisement). Are we making it easier to consume? In my opinion, the answer is no (and we are not solving a real issue anyway)

@dplore
Copy link
Member

dplore commented Sep 24, 2024

Reviewed in Sep 24, 2024 OC Operators meeting:

It seems the model already has the leaves we need

  • port-speed for singleton interfaces (non-lag / non-aggregate ports)
  • aggregation/state/lag-speed for aggregate / lag interfaces

This PR introduces a change to limit port-speed to only be present when interface type is iana-if-type:ethernetCsmacd

lag-speed is already conditional on ianaift:ieee8023adLag

So in concept this PR looks good.

The CI check with pyang detected some issue, probably related to naming changes in the yang groupings. Can you fix @earies ?

Apologies for any confusion on my earlier naive comment about adding a leaf as we already have the leaf I was thinking about (lag-speed).

@dplore dplore linked an issue Sep 24, 2024 that may be closed by this pull request
@earies
Copy link
Contributor Author

earies commented Sep 24, 2024

The CI check with pyang detected some issue, probably related to naming changes in the yang groupings. Can you fix @earies ?

This check actually appears to open a can of worms on the design and integration of wifi related modules (something I have not really paid attention to the progressions over the years)

The wifi modules make heavy reuse of other published models - for this case openconfig-if-ethernet - however redefine trees up to a certain anchor point and use groupings from other modules thus absorbing wifi related namespaces (and thus creating issues for prefix checks in when/must clauses) - short excerpt of where the offending clause is triggered below (note the prefixes in use):

module: openconfig-access-points
  +--rw access-points
     +--rw access-point* [hostname]
        +--rw oc-ap-if:interfaces
           +--rw oc-ap-if:interface* [name]
              +--rw oc-ap-if:name             -> ../config/name
              +--rw oc-ap-if:config
              |  +--rw oc-ap-if:name?            string
              |  +--rw oc-ap-if:type             identityref
              |  +--rw oc-ap-if:mtu?             uint16
              |  +--rw oc-ap-if:loopback-mode?   oc-opt-types:loopback-mode-type
              |  +--rw oc-ap-if:description?     string
              |  +--rw oc-ap-if:enabled?         boolean

This then means that the when restriction introduced here cannot be qualified for the wifi modules because they carry a different prefix in the relative path (oc-ap-if:) from an entirely different module. This new when statement also cannot accommodate including the reuse of groupings in wifi as that would create a circular dependency between the modules (needing to import the wifi modules into the core interface modules).

The wifi modules appear to implement a controller/service viewpoint vs. a network-element viewpoint exacerbating the issue (as intents then differ) with grouping reuse and imposing restrictions into used model-sets.

Due to the design and colocation of the wifi modules with what are mostly router/switch feature set device modules, it appears we have a design consideration we need to discuss further as I cannot see any elegant way out of this atm.

cc: @mike-albano

@LimeHat
Copy link

LimeHat commented Sep 25, 2024

For this particular change, perhaps a simple description update would be sufficient?

@earies
Copy link
Contributor Author

earies commented Sep 28, 2024

For this particular change, perhaps a simple description update would be sufficient?

Sadly that is the likely fastest/easiest option here but this represents a bigger issue. Raised #1193 for further discussion

@dplore
Copy link
Member

dplore commented Oct 4, 2024

/gcbrun

@earies
Copy link
Contributor Author

earies commented Oct 7, 2024

@cfyo @dplore - please re-review - the PR has been updated to remove any when statements and describe behavior within description statements. This should be looked at as a temporary solution until we address the bigger problem statement on model reuse/inheritance.

@dplore dplore added the last-call PR that is in final review before merging. label Oct 8, 2024
@dplore
Copy link
Member

dplore commented Oct 8, 2024

/gcbrun

@dplore
Copy link
Member

dplore commented Oct 8, 2024

Setting last call for comments on Oct 22, 2024

@cfyo
Copy link
Contributor

cfyo commented Oct 21, 2024

I'm good with the description update for now but this needs to be resolved in #1193

@dplore
Copy link
Member

dplore commented Oct 21, 2024

/gcbrun

@dplore
Copy link
Member

dplore commented Oct 29, 2024

/gcbrun

@dplore
Copy link
Member

dplore commented Oct 29, 2024

@earies can you provide a tree rendering? I am not seeing any breaking change now? If that is true, can you revise the model version to a non-breaking change?

@earies
Copy link
Contributor Author

earies commented Oct 31, 2024

@earies can you provide a tree rendering? I am not seeing any breaking change now? If that is true, can you revise the model version to a non-breaking change?

Addressed in latest commit and update to the initial PR description

@dplore
Copy link
Member

dplore commented Oct 31, 2024

/gcbrun

@dplore dplore merged commit 4af7a68 into openconfig:master Oct 31, 2024
14 checks passed
@earies earies deleted the interface-speeds branch November 1, 2024 07:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
last-call PR that is in final review before merging. non-breaking
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

Ethernet port speed for aggregated interfaces
5 participants