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

  import ietf-interfaces {
    prefix if;
    reference
      "RFC 8343: A YANG Data Model For Interface Management";
  }
  import ietf-yang-types {
    prefix yang;
    reference
      "RFC 6991: Common YANG Data Types";
  }

  organization
    "IETF Benchmarking Methodology Working Group";
  contact
    "WG Web:   <http://tools.ietf.org/wg/bmwg/>
     WG List:  <mailto:bmwg@ietf.org>

     Editor:   Vladimir Vassilev
               <mailto:vladimir@lightside-instruments.com>";
  description
    "This module contains a collection of YANG definitions for
     description and management of network interconnect testers.

     Copyright (c) 2022 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 Revised 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; see
     the RFC itself for full legal notices.";

  revision 2022-10-22 {
    description
      "Initial revision.";
    reference
      "RFC XXXX: A YANG Data Model for
       Network Tester Management";
  }

  feature egress-direction {
    description
      "The device can analyze traffic from the egress direction.";
  }

  feature ingress-direction {
    description
      "The device can generate traffic from the ingress direction.";
  }

  feature filter {
    description
      "This feature indicates that the device implements
       filter that can specify a subset of packets to be
       analyzed when filtering is enabled.";
  }

  feature idle-octets-counter {
    description
      "This feature indicates that the device implements
       idle-octets counter that accumulates the time
       the link is not utilized. The minimum required
       idle gaps are not counted as idle octets.";
  }
  feature capture {
    description
      "This feature indicates that the device implements
       packet capture functionality.";
  }

  identity filter {
    description
      "Base filter identity.";
  }

  identity ethernet {
    base ntta:filter;
    description
      "Ethernet packet fields filter.";
  }

  grouping statistics-data {
    description
      "Analyzer statistics.";
    leaf pkts {
      type yang:counter64;
      description
        "Total number of packets analyzed.";
    }
    leaf octets {
      type yang:counter64;
      description
        "This counter is identical with the in-octets/out-octets
         counters defined in RFC8343 except that it counts the
         octets since the analyzer was created.";
    }
    leaf idle-octets {
      if-feature "idle-octets-counter";
      type yang:counter64;
      description
        "Total accumulated period with no frame transmission
         taking place measured in octets at the current link
         speed. Octets not counted in ../octets but not idle are
         for example layer 1 framing octets - for Ethernet interfaces
         7+1 preamble octets per packet.";
    }
    leaf errors {
      type yang:counter64;
      description
        "Count of packets with errors.
         Not counted in the pkts or captured.
         For example packets with CRC error.";
    }
    container testframe-stats {
      description
        "Statistics for testframe packets containing
         either sequence number, payload checksum,
         timestamp or any combination of these features.";
      leaf testframe-pkts {
        type yang:counter64;
        description
          "Total count of detected testframe packets.";
      }
      leaf sequence-errors {
        type yang:counter64;
        description
          "Total count of testframe packets with
           unexpected sequence number. After each sequence
           error the expected next sequence number is
           updated.";
      }
      leaf payload-errors {
        type yang:counter64;
        description
          "Total count of testframe packets with
           payload errors.";
      }
      container latency {
        description
          "Latency statistics.";
        leaf samples {
          type uint64;
          description
            "Total count of packets used for estimating
             the latency statistics. Ideally
             samples=../testframe-stats.";
        }
        leaf min {
          type uint64;
          units "nanoseconds";
          description
            "Minimum measured latency.";
        }
        leaf max {
          type uint64;
          units "nanoseconds";
          description
            "Maximum measured latency.";
        }
        leaf average {
          type uint64;
          units "nanoseconds";
          description
            "The sum of all sampled latencies divided
             by the number of samples.";
        }
        leaf latest {
          type uint64;
          units "nanoseconds";
          description
            "Latency of the latest sample.";
        }
      }
    }
  }

  grouping capture-config-data {
    description
      "Grouping with a capture configuration container.";
    container capture {
      if-feature "capture";

      description
        "Contains capture parameters.";

      container start-trigger {
          description
            "Configures when the capture start is triggered.";
        choice start-trigger {
          description
            "If none of the cases in this choice are configured the
             capture process starts from the first frame received.";
          case frame-index {
            description
              "Start capturing frames at the specified frame index.";
            leaf frame-index {
              type uint64;
              description
                "First captured frame index.";
            }
          }
          case testframe-index {
            description
              "Start capturing frames at the specified
               testframe index.";
            leaf testframe-index {
              type uint64;
              description
                "Starts capture as specified testframe index.";
            }
          }
        }
      }
      container stop-trigger {
          description
            "Configures when the capture is stopped.";
        choice stop-trigger {
          description
            "If none of the cases in this choice are configured the
             captured frames are always the last frames received for
             as many frames the implementation can buffer.";
          case when-full {
            description
              "Stops capturing when the implementation can not store
               more frames.";
            leaf when-full {
                type empty;
                description
                  "When present in configuration capture stops when
                   the capture buffer is full.";
            }
          }
        }
      }
    }
  }

  grouping capture-data {
    description
      "Grouping with statistics and data
       of one or more captured frame.";
    container capture {
      if-feature "capture";
      description
        "Statistics and data of
         one or more captured frames.";
      list frame {
        key "sequence-number";
        description
          "Statistics and data of a captured frame.";
        leaf sequence-number {
          type uint64;
          description
            "Incremental counter of frames captured.";
        }
        leaf timestamp {
          type yang:date-and-time;
          description
            "Timestamp of the moment the frame was captured.";
        }
        leaf length {
          type uint32;
          description
            "Frame length. Ideally the data captured will be
             of the same length but can be shorter
             depending on implementation limitations.";
        }
        leaf preceding-interframe-gap {
          type uint32;
          units "nanoseconds";
          description
            "Measured delay between the reception of the previous
             frame was completed and the reception of the current
             frame was started.";
        }
        leaf data {
          type string {
            pattern '([0-9A-F]{2})*';
          }
          description
            "Raw data of the captured frame.";
        }
      }
    }
  }

  grouping filter-data {
    description
      "Grouping with a filter container specifying the filtering
       rules for processing only a specific subset of the
       frames.";
    container filter {
      if-feature "filter";
      presence "When present packets are
                filtered before analyzed according
                to the filter type";
      description
        "Contains the filtering rules for processing only
         a specific subset of the frames.";
      leaf type {
        type identityref {
          base ntta:filter;
        }
        mandatory true;
        description
          "Type of the applied filter. External modules can
           define alternative filter type identities.";
      }
    }
  }

  augment "/if:interfaces/if:interface" {
    description
      "Traffic analyzer augmentations of ietf-interfaces.";
    container traffic-analyzer {
      if-feature "ingress-direction";
      presence "Enables the traffic analyzer for ingress traffic.";
      description
        "Traffic analyzer for ingress direction.";
      uses filter-data;
      uses capture-config-data;
      container state {
        config false;
        description
          "State data.";
        uses statistics-data;
        uses capture-data;
      }
    }
    container traffic-analyzer-egress {
      if-feature "egress-direction";
      presence "Enables the traffic analyzer for egress traffic.";
      description
        "Traffic analyzer for egress direction.";
      uses filter-data;
      uses capture-config-data;
      container state {
        config false;
        description
          "State data.";
        uses statistics-data;
        uses capture-data;
      }
    }
  }

  augment "/if:interfaces/if:interface/ntta:traffic-analyzer/"
        + "ntta:filter" {
    when "derived-from-or-self(ntta:type, 'ntta:ethernet')";
    description
      "Ethernet frame specific filter type.";
    leaf ether-type {
      type uint16;
      description
        "The Ethernet Type (or Length) value
         defined by IEEE 802.";
      reference
        "IEEE 802-2014 Clause 9.2";
    }
  }
}
