module ietf-flexe {
  yang-version 1.1;
  namespace "urn:ietf:params:xml:ns:yang:ietf-flexe";
  prefix "flexe";

  import iana-if-type {
    prefix ianaift;
  }
  import ietf-interfaces {
    prefix if;
    reference
     "RFC8343: A YANG Data Model for Interface Management";
  }

  organization "IETF CCAMP Working Group";
  contact
    "WG Web:   http://tools.ietf.org/wg/ccamp/
     WG List:  <mailto:ccamp@ietf.org>
     Author:   Yuanlong Jiang
               <mailto:jiangyuanlong@huawei.com>
     Author:   Xiang He
               <mailto: hexiang@huawei.com>
     Author:   Weiqiang Cheng
               <mailto: chengweiqiang@chinamobile.com>
     Author:   Junfang Wang
               <mailto: wjf@fiberhome.com>
     Author:   Yalei Han
               <mailto: ylhan@fiberhome.com>";
  description
    "This YANG module defines a data model for the configuration
     of FlexE interface.";

  revision "2019-10-30" {
    description "Initial version";
    reference
     "draft-jiang-ccamp-flexe-yang-02: YANG Data Model for FlexE
      Interface Management ";
  }
  identity flexEthernet {
    base ianaift:iana-interface-type;
    description
      "Flex Ethernet.";
  }

  typedef slot-granularity-enumeration {
    type enumeration {
      enum slot-5g {
        value 1;
        description
          "5Gbps per slot.";
      }
      enum slot-25g {
        value 2;
        description
          "25Gbps per slot.";
      }
      enum slot-others {
        value 254;
        description
          "Other type of granularities per slot.";
      }
    }
    description
      "The bandwidth granularity of a slot. Options for this
      enumeration are specified by the OIF standard, currently only
      5G and 25G are defined.";
    reference
      "OIF Flex 2.0: Section 6.7";
  }

  typedef slot-status-enumeration {
    type enumeration {
      enum unavailable {
        value 1;
        description
          "slot is unavailable for a FlexE client.";
      }
      enum unused {
        value 2;
        description
          "slot is unused.";
      }
      enum used {
        value 3;
        description
          "slot is used.";
      }
    }
    description
      "The status of a slot in a PHY. Options for this enumeration
       are specified by the OIF standard, 'used' is implicit.";
    reference
      "OIF Flex 2.0: Section 7.3.4 and Section 7.6";
  }

  typedef flexe-phy-enumeration {
    type enumeration {
      enum 'PHY-100GBASE-R' {
        value 1;
        description
          "100GBASE-R PHY, as defined in FlexE 1.0.";
      }
      enum 'PHY-200GBASE-R' {
        value 2;
        description
          "200GBASE-R PHY, as defined in FlexE 2.0.";
      }
      enum 'PHY-400GBASE-R' {
        value 3;
        description
          "400GBASE-R PHY, as defined in FlexE 2.0.";
      }
      enum 'PHY-50GBASE-R' {
        value 4;
        description
          "50GBASE-R PHY, as defined in FlexE 2.1.";
      }
    }

    description
      "The current type of PHYs bonded in a FlexE Group. Values for
       this enumeration are specified by the OIF standard.";
    reference
      "OIF Flex 2.0 and 2.1: Section 5.2.1.5";
  }

  typedef phy-status-enumeration {
       type enumeration {
            enum phy-status-OK {
           value 0;
           description
             "The FlexE PHY status is ok";
         }
         enum phy-status-LOF {
           value 1;
           description
             "The FlexE PHY status is Loss of Frame";
         }
         enum phy-status-RPF {
           value 2;
           description
             "The FlexE PHY status is Remote PHY Fault";
         }
         enum phy-status-LPF {
           value 3;
           description
             "The FlexE PHY status is Local PHY Fault";
         }
       }
       description
         "The current PHY status. RPF, LPF, LOF and OK are defined.";
       reference
         "OIF Flex 2.0: Section 7.3.8";
  }

  typedef client-status-enumeration {

    type enumeration {
            enum flexe-client-status-OK {
            value 0;
            description
             "The FlexE client status is OK";
            }
            enum flexe-client-status-LF {
              value 1;
              description
                "The FlexE client status is Local Fault";
            }
            enum flexe-client-status-RF {
              value 2;
              description
                "The FlexE client status is Remote Fault";
         }
    }
    description
      "The client status. RPF, LPF and OK are defined.";
    reference
      "OIF Flex 2.0: Section 7.3.8";
  }

  augment "/if:interfaces/if:interface" {

    when "if:type = 'ianaift:flexEthernet'" {
      description "Applies to Flex bonded Ethernet interfaces";
    }

    description
      "Augment interface model with OIF Flex Ethernet interface
       specific configuration nodes. Each flexEthernet interface
       represents a FlexE Group configured in a device.";

    container flexe-group {
      description
        "The struct containing all FlexE related configuration
         (see OIF FlexE 2.0 Section 6.1).
         Note that max number of FlexE groups in a network is 63.";

      leaf group-number {
        type uint32 {
          range "1..1048574";
        }
        description
          "FlexE Group Number as defined in Section 7.3.6 of FlexE
           2.0.";
      }

      leaf slot-granularity {
        type slot-granularity-enumeration;
        default "slot-5g";
        description
           "The granularity of a slot in a FlexE group.";
      }
      leaf flexe-phy-type {
        type flexe-phy-enumeration;
        default "PHY-100GBASE-R";
        description
           "The type of PHYs bonded in a FlexE Group.";
      }

      leaf calendar-protocol-enable {
          type boolean;
          default true;
          description
            "Whether calendar negotiation protocol is enabled or
             not.";
          reference
            "OIF Flex 2.0: Section 7.3.4";
      }

     list flexe-phy-list {

       key "flexe-phy-if";
       description
         "List of PHYs bonded in a FlexE group.";

       leaf flexe-phy-if {
         type if:interface-ref;
         description
           "Reference to a Flexe PHY interface.";
       }

       leaf phy-number {
         type uint8 {
           range "1 .. 254";
         }
         description
           "PHY number of a FlexE PHY.
            If PHY type is 100GBASE-R, phy-number is [1,254].
            If PHY type is 200GBASE-R, phy-number is [1,126].
            If PHY type is 400GBASE-R, phy-number is [1, 62].";
       }

       leaf flexe-phy-status {
          type phy-status-enumeration;
          default "phy-status-OK";
          config false;
         description
           "The FlexE PHY status.";
       }

       list calendar-slot-list {
         key "slot-id";
         leaf slot-id {
           type uint8;
           description
             "slot id of a slot in a PHY.";
         }
         description
           "List of slots in a FlexE PHY. Max elements of
            slot-list for a FlexE PHY is dependent on the PHY
            bandwidth (X)G and the slot granularity (Y)G, i.e.,
            X/Y. For example, for a 400GBASE-R PHY:
            If slot-granularity=slot-5g, max-elements is 80.
            If slot-granularity=slot-25g, max-elements is 16.";

         leaf flexe-slot-status {
           type slot-status-enumeration;
           default unused;
           config false;
           description
             "Slot status of a FlexE slot.";
         }
       } //calendar-slot-list
     } //flexe-phy-list

     list flexe-client-list {

       key "client-id";
       description
         "List of FlexE clients in a FlexE Group.";
       leaf client-id {
         type uint16 {
           range "1..65534";
         }
         description
           "FlexE Client field as defined in FlexE 2.0 Section
            7.3.4.";
       }

       leaf flexe-client-if {
         type if:interface-ref;
         description
           "The type of a flexe client interface must be
            'flexeClient'.";
       }

       list client-slot-list {
         key "client-slot-id";
         min-elements 1;
         description
           "List of slots for a FlexE client.";
         leaf client-slot-id {
           type uint8;
           description
             "Client slot id of a client slot in sequence for a
              client.";
         }

         leaf mapped-phy-if {
           type if:interface-ref;
           description
             "Mapped PHY interface of a client slot.";
         }
         leaf mapped-slot-id {
           type uint8;
           description
             "Mapped Slot id of a client slot in the mapped PHY.
              If a slot [i] is mapped, flexe-slot-status[i] in the
              Mapped PHY MUST be set to 'used' ";
         }
       } // client-slot-list

       leaf flexe-client-status {
          type client-status-enumeration;
          default flexe-client-status-OK;
          config false;
         description
           "The FlexE client status.";
        }

     } //flexe-client-list

     leaf flexe-group-status {
       type uint8;
       config false;
       description
         "Status for a FlexE Group. If any PHY is in fault,
          or any FlexE configuration is mismatched, the FlexE
          Group status is indicated in fault. Status includes:
             OK, Local Fault, Remote Fault, mismatch and etc.";
     }
    } //flexe-group
  }  //augment
}
