submodule infix-if-lag {
  yang-version 1.1;
  belongs-to infix-interfaces {
    prefix infix-if;
  }

  import ietf-interfaces {
    prefix if;
  }
  import iana-if-type {
    prefix ianaift;
  }
  import ietf-inet-types {
    prefix inet;
  }
  import ietf-yang-types {
    prefix yang;
  }

  organization "KernelKit";
  contact      "kernelkit@googlegroups.com";
  description  "Linux link aggregates (lag) for ietf-interfaces.";

  revision 2025-03-28 {
    description "Drop unused must expressions for link and arp monitor.";
    reference "internal";
  }

  revision 2025-01-09 {
    description "Initial revision.";
    reference "internal";
  }

  /*
   * Typedefs
   */

  typedef lag-mode {
    description "Mode values for link aggregates.";

    type enumeration {
      enum static {
        description "Static mode (Balanced XOR).";
      }
      enum lacp {
        description "IEEE 802.3ad LACP mode.";
      }
    }
  }

  typedef lag-type {
    description "Static mode type of distribution (driver modes).";

    type enumeration {
      enum balance-rr;
      enum active-backup;
      enum balance-xor;
      enum broadcast;
      enum balance-tlb;
      enum balance-alb;
    }
  }

  typedef hash-policy {
    description "Egress hash policy, note: offloading limitations!";

    type enumeration {
      enum layer2;
      enum layer3-4;
      enum layer2-3;
      enum encap2-3;
      enum encap3-4;
      enum vlan-srcmac;
    }
  }

  typedef member-state {
    description "Lag port membership state, taking active part or backup.";

    type enumeration {
      enum backup;
      enum active;
    }
  }

  typedef lacp-mode {
    description "LACP mode values.";

    type enumeration {
      enum passive {
        description "LACP passive mode";
      }
      enum active {
        description "LACP active mode.";
      }
    }
  }

  typedef lacp-rate {
    description "LACP rate values.";

    type enumeration {
      enum slow {
        description "Send LACPDUs every 30 seconds (90-second timeout).";
      }
      enum fast {
        description "Send LACPDUs every 1 second (3-second timeout).";
      }
    }
  }

  typedef lacp-state {
    description "LACP port state flags.";

    type enumeration {
      enum active;
      enum short_timeout;
      enum aggregating;
      enum in_sync;
      enum collecting;
      enum distributing;
      enum defaulted;
      enum expired;
    }
  }

  /*
   * Shared settings
   */

  grouping hash {
    leaf hash {
      description "Transmit hash policy.";
      type hash-policy;
      config false;               // For now, staically set to layer2 only
    }
  }

  /*
   * Data Nodes
   */

  augment "/if:interfaces/if:interface" {
    when "derived-from-or-self(if:type,'ianaift:ieee8023adLag')" {
        description "Only shown for if:type bridge";
    }

    description "Augment generic interfaces with link aggregates.";

    container lag {
      description "Link aggregates are for load balancing and fault tolerance.";

      leaf mode {
        description "Link aggregation mode.";
        type lag-mode;
        mandatory true;
      }

      container lacp {
        description "Settings specific for LACP mode.";

        uses hash;

        leaf mode {
          description "Operational mode of LACP, default: active.

                        - Active: initiates negotiation by sending LACPDUs.
                        - Passive: waits for the peer to initiate.

                       At least one end of the link must be in active mode. When both ends
                       are active, there is slightly more traffic, but the default ensures
                       fail-safe operation.

                       Passive mode is typically used for troubleshooting, in dynamic
                       setups (e.g., MLAG), or to minimize the risk of unintended
                       aggregation.

                       For most production scenarios, active mode is preferred to ensure
                       faster and more predictable link aggregation.";
          type lacp-mode;
          default active;
        }

        leaf rate {
          description "Rate of LACP keep-alives, default: slow.

                       Determines the frequency of LACPDU transmission and the associated
                       timeout for link failure detection.

                        - slow: Sends LACPDUs every 30 seconds. The associated timeout is 90
                          seconds, meaning a link is considered failed after 3 consecutive
                          missed LACPDUs.

                        - fast: Sends LACPDUs every 1 second. The associated timeout is 3
                          seconds, meaning a link is considered failed after 3 consecutive
                          missed LACPDUs.

                       The selected rate affects the responsiveness of link failure
                       detection and the amount of control traffic.";
          type lacp-rate;
          default slow;
        }

        leaf system-priority {
          description "Sytem priority used by the node on this LAG interface.

                       Lower value is higher priority for determining which node
                       is the controlling system.";
          type uint16 {
            range "1 .. 65535";
          }
        }

        leaf aggregator-id {
          description "Aggregator ID.";
          config false;
          type uint16;
        }

        leaf actor-key {
          description "Actor key.";
          config false;
          type uint16;
        }

        leaf partner-key {
          description "Partner key.";
          config false;
          type uint16;
        }

        leaf partner-mac {
          description "Partner MAC address.";
          config false;
          type yang:phys-address;
        }
      }

      container static {
        config false;               // For now, we need to read out mode and other status

        leaf mode {
          description "Active mode for static aggregates.";
          type lag-type;
        }

        uses hash;
      }

      container link-monitor {
        description "Link monitor properties.";

        container debounce {
          description "Link flapping protection.";

          leaf up {
            description "Wait before enabling link after link up.";
            type uint32 {
              range "0 .. 30000";
            }
            units "milliseconds";
          }

          leaf down {
            description "Wait before disabling link after link down.";
            type uint32 {
              range "0 .. 30000";
            }
            units "milliseconds";
          }
        }
      }
    }
  }

  augment "/if:interfaces/if:interface/infix-if:port" {
    when "derived-from-or-self(if:type,'ianaift:ethernetCsmacd') or "+
         "derived-from-or-self(if:type,'ianaift:ilan')" {
      description "Applies when a LAG interface exists.";
    }

    description "Augments the interface model with the link aggregate member.";

    case lag-port {
      description "Extension of the IETF Interfaces model (RFC7223).";

      container lag-port {
        leaf lag {
          description "LAG interface to which this interface is a member of.";
          type if:interface-ref;
          mandatory true;
          must "deref(.)/../lag" {
            error-message "Must refer to a valid LAG interface.";
          }
        }

        leaf state {
          description "Link state, active or backup member.";
          type member-state;
          config false;
        }

        leaf link-failures {
          description "Link failure counter, cannot be reset.";
          type uint32;
          config false;
        }

        container lacp {
          description "LACP port state, ours and partner.";
          config false;

          leaf aggregator-id {
            description "Aggregator ID.";
            type uint16;
          }

          leaf-list actor-state {
            description "LACP state flags.";
            type lacp-state;
          }

          leaf-list partner-state {
            description "LACP state flags for link partner.";
            type lacp-state;
          }
        }
      }
    }
  }
}
