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:   <http://tools.ietf.org/wg/netmod/>
     WG List:  <mailto:netmod@ietf.org>

     Editor:   Robert Wilton
               <mailto:rwilton@cisco.com>";

  description
    "This module contains common definitions for extending the IETF
     interface YANG model (RFC 8343) with common configurable layer 2
     properties.

     Copyright (c) 2019 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 Simplified 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 2019-11-04 {
    description
      "Initial revision.";

    reference
      "RFC XXX, Common Interface Extension YANG Data Models";
  }

  feature carrier-delay {
    description
      "This feature indicates that configurable interface
       carrier delay is supported, which is a feature is used to
       limit the propagation of very short interface link state
       flaps.";
    reference "RFC XXX, Section 2.1 Carrier Delay";
  }

  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 XXX, Section 2.2 Dampening";
  }

  feature loopback {
    description
      "This feature indicates that configurable interface loopback
       is supported.";
    reference "RFC XXX, 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 XXX, 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 XXX, 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 XXX, 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 XXX, 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 XXX, 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 XXX, 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 XXX, Section 2.4";
  }


  identity forwarding-mode {
    description "Base identity for forwarding-mode options.";
    reference "RFC XXX, Section 2.7";
  }
  identity physical {
    base forwarding-mode;
    description
      "Physical layer forwarding.  This includes DWDM or OTN based
       optical switching.";
    reference "RFC XXX, 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 XXX, Section 2.7";
  }
  identity network {
    base forwarding-mode;
    description
      "Network layer based forwarding, such as IP, MPLS, or L3VPNs.";
    reference "RFC XXX, Section 2.7";
  }


  /*
   * Augments the IETF interfaces model with leaves to configure
   * and monitor carrier-delay 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 Carrier Delay feature.
     */
    container carrier-delay {
      if-feature "carrier-delay";
      description
        "Holds carrier delay 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 carrier signal must be continuously
           down before the interface state is brought down. If not
           configured, the behaviour on loss of carrier 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 carrier signal must be continuously present and error
           free before the interface state is allowed to transition
           from down to up.  If not configured, the behaviour 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 carrier 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 carrier-delay timer.";
      }
      leaf timer-running {
        type enumeration {
          enum none {
            description
              "No carrier delay timer is running.";
          }
          enum up {
            description
              "Carrier-delay up timer is running.  The underlying
               carrier state is up, but interface state is not
               reported as up.";
          }
          enum down {
            description
              "Carrier-delay down timer is running.  Interface state
               is reported as up, but the underlying carrier state is
               actually down.";
          }
        }
        config false;
        description
          "Reports whether a carrier delay timer is actively running,
           in which case the interface state does not match the
           underlying carrier state.";
      }

      reference "RFC XXX, Section 2.1 Carrier Delay";
    }

    /*
     * 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 XXX, 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 XXX, 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 XXX, 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 XXX, 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 XXX, 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 XXX, 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 XXX, 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 XXX, 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, '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 XXX, 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 XXX, 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 XXX, 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 XXX, 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: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 XXX, Section 2.6 Sub-interface";
    }
  }
}
