module ietf-network-bridge-flows {
  namespace "urn:ietf:params:xml:ns:yang:ietf-network-bridge-flows";
  prefix flow;

  import ietf-network-bridge {
    prefix netbr;
  }
  import ietf-inet-types {
    prefix inet;
  }
  import ietf-yang-types {
    prefix yang;
  }

  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:   Vladimir Vassilev
               <mailto:vladimir@lightside-instruments.com>";
  description
    "This module contains a collection of YANG definitions for
     description and management of network bridge based on
     flows.

     Copyright (c) 2020 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
     (http://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 2021-02-17 {
    description
      "Unreleased revision.";
    reference
      "RFC XXXX: Network Bridge";
  }

  identity packet-in-reason {
    description
      "Base identity for all the available packet in reasons.";
  }

  identity no-match {
    base packet-in-reason;
    description
      "No matching flow in the classifier";
  }

  identity send-to-controller {
    base packet-in-reason;
    description
      "Explicit instruction to send packet to controller";
  }

  identity invalid-ttl {
    base packet-in-reason;
    description
      "Packet with invalid TTL";
  }

  typedef vlan-pcp {
    type uint8 {
      range "0..7";
    }
    description
      "IEEE 802.1p priority. It indicates the frame priority level.
       Values are from 0 (best effort) to 7 (highest);
       1 represents the lowest priority.";
  }

  typedef vlan-id {
    type uint16 {
      range "0..4095";
    }
    description
      "IETF 802.1q VLAN tag id.";
  }

  typedef ether-type {
    type uint16;
    description
      "Length/Type field of the generated Ethernet packet.";
    reference
      "IEEE 802-2014 Clause 9.2";
  }

  typedef vlan-cfi {
    type int32;
    description
      "Canonical Format Identifier (CFI) field
       (shall be 0 for Ethernet switches) of the
       transmitted 802.1q VLAN tag.";
  }

  typedef flow-id {
    type inet:uri;
    description
      "Flow identifier.";
  }

  grouping address {
    description
      "IP address.";
    choice address {
      description
        "Address choice.";
      case ipv4 {
        leaf ipv4-address {
          type inet:ipv4-prefix;
          description
            "IPv4 address.";
        }
      }
      case ipv6 {
        leaf ipv6-address {
          type inet:ipv6-prefix;
          description
            "IPv6 address.";
        }
      }
    }
  }

  grouping action-list {
    description
      "Action list grouping.";
    list action {
      key "order";
      description
        "Contains action with corresponding order index.";
      leaf order {
        type int32;
        description
          "Order index.";
      }
      uses action;
    }
  }

  grouping action {
    description
      "Grouping of all action data definitions.";
    choice action {
      description
        "Choice with alternative action cases.";
      case output-action-case {
        container output-action {
          description
            "Contains output action specific data.";
          leaf out-port {
            type netbr:port-ref;
            description
              "Port on which the packet is sent.";
          }
          leaf max-length {
            type uint16;
            description
              "Packets above this length are discarded.";
          }
        }
      }
      case controller-action-case {
        container controller-action {
          description
            "Contains controller action specific data.";
          leaf max-length {
            type uint16;
            description
              "Packets above this length are discarted.";
          }
        }
      }
      case drop-action-case {
        container drop-action {
          presence "Drop action case";
          description
            "Drop action presence container.";
        }
      }
      case pop-vlan-action-case {
        container pop-vlan-action {
          presence "Pop-vlan action case.";
          description
            "Pop-vlan presence container";
        }
      }
      case push-vlan-action-case {
        container push-vlan-action {
          description
            "Contains push-vlan action specific data.";
          leaf ethernet-type {
            type ether-type;
            description
              "Tag protocol identifier (TPID) as defined in
               IEEE 802.1q";
          }
          leaf pcp {
            type vlan-pcp;
            description
              "Specifies the IEEE 802.1p Priority Code Point (PCP) value
               of the pushed 802.1q VLAN tag.";
          }
          leaf cfi {
            type vlan-cfi;
            description
              "Configures the Canonical Format Identifier (CFI) field
               (shall be 0 for Ethernet switches) of the transmitted
               802.1q VLAN tag.";
          }
          leaf vlan-id {
            type vlan-id;
            description
              "Specifies the VLAN ID as defined in IEEE 802.1q of the
               pushed VLAN tag.";
          }
        }
      }
      case set-vlan-cfi-action-case {
        container set-vlan-cfi-action {
          description
            "Contains set-vlan-cfi action specific data. The
             set-vlan-cfi action is used to replace CFI field
             on already tagged packets.";
          leaf vlan-cfi {
            type vlan-cfi;
            description
              "Configures the Canonical Format Identifier (CFI) field
               to set on the transmitted 802.1q VLAN tagged packet.";
          }
        }
      }
      case set-vlan-id-action-case {
        container set-vlan-id-action {
          description
            "Contains set-vlan-id action specific data. The set-vlan-id
             action is used to replace VLAN ID field on already tagged
             packets.";
          leaf vlan-id {
            type vlan-id;
            description
              "Specifies the VLAN ID to set on the 802.1q VLAN tagged
               packet.";
          }
        }
      }
      case set-vlan-pcp-action-case {
        container set-vlan-pcp-action {
          description
            "Contains set-vlan-pcp action specific data. The
             set-vlan-pcp action is used to replace VLAN PCP
             field on already tagged packets.";
          leaf vlan-pcp {
            type vlan-pcp;
            description
              "Specifies the IEEE 802.1p Priority Code Point
               (PCP) value to set on the 802.1q VLAN tagged
               packet.";
          }
        }
      }
      case strip-vlan-action-case {
        container strip-vlan-action {
          presence "Strip-vlan action case";
          description
            "Strip-vlan presence container.";
        }
      }
    }
  }

  grouping mac-address-filter {
    description
      "Defines address and mask pair for
       definition of basic MAC address filter rules.";
    leaf address {
      type yang:mac-address;
      mandatory true;
      description
        "MAC address to compare with.";
    }
    leaf mask {
      type yang:mac-address;
      description
        "The mask specifies the bits to compare.
         All bits that are 1s are significant.";
    }
  }

  grouping ethernet-match-fields {
    description
      "Defines data for specification of filter rules for Ethernet
       frames based on source and destination MAC addresses and
       the ethernet type field.";
    container ethernet-source {
      presence "Match field is active and set";
      description
        "Ethernet source address.";
      uses mac-address-filter;
    }
    container ethernet-destination {
      presence "Match field is active and set";
      description
        "Ethernet destination address.";
      uses mac-address-filter;
    }
    container ethernet-type {
      presence "Match field is active and set";
      description
        "Ethernet frame type.";
      leaf type {
        type ether-type;
        mandatory true;
        description
          "Type field of the Ethernet frame.";
      }
    }
  }

  grouping vlan-match-fields {
    description
      "Defines data for specification of filter rules for
       VLAN tagged or not Ethernet frames based on the
       presence of VLAN tag, the value of the VLAN ID and
       VLAN PCP fields.";
    container vlan-id {
      presence "Match field is active and set";
      description
        "Match 802.1q VLAN ID.";
      leaf vlan-id-present {
        type boolean;
        description
          "If set to false match packets with different
           VLAN ID then the specified in the vlan-id leaf.";
      }
      leaf vlan-id {
        type vlan-id;
        description
          "802.1q VLAN ID to match. The match rule can
           be inverted by setting vlan-id-present to
           false.";
      }
    }
    leaf vlan-pcp {
      type vlan-pcp;
      description
        "Match 802.1p VLAN Priority code point (PCP) field.";
    }
  }

  grouping match {
    description
      "Defines data for specification of filter rules.";
    leaf in-port {
      type netbr:port-ref;
      description
        "Input port to match.";
    }
    container ethernet-match {
      description
        "Ethernet match rules.";
      uses ethernet-match-fields;
    }
    container vlan-match {
      description
        "VLAN match rules.";
      uses vlan-match-fields;
    }
  }

  grouping raw-packet {
    description
      "Basic packet structure.";
    leaf ingress {
      type netbr:port-ref;
      description
        "Port the packet was received on.";
    }
    leaf payload {
      type binary;
      description
        "Payload of the packet.";
    }
  }

  grouping packet-in {
    description
      "Input packet event data:
       ingress port, payload, event reason.";
    leaf packet-in-reason {
      type identityref {
        base packet-in-reason;
      }
      description
        "Reason identity:
         no-match, send-to-controller, invalid-ttl or another
         reason for the corresponding packet-in event.";
    }
    uses raw-packet;
  }

  grouping ethernet-packet {
    description
      "Ethernet packet headers structure.";
    leaf source {
      type yang:mac-address;
      description
        "MAC source address.";
    }
    leaf destination {
      type yang:mac-address;
      description
        "MAC destination address.";
    }
  }

  grouping flow {
    description
      "The definition of a flow has a name,
       match container specifying filter rules and
       ordered list of actions to be performed on
       each packet.";
    leaf id {
      type flow-id;
      description
        "Flow identifier.";
    }
    container match {
      description
        "Filter rules for the flow.";
      uses match;
    }
    container actions {
      description
        "Ordered list of actions.";
      uses action-list;
    }
  }

  rpc transmit-packet {
    description
      "Sending packet out.";
    input {
      leaf egress {
        type netbr:port-ref;
        description
          "Egress port the packet will be transmitted from.";
      }
      uses raw-packet;
      uses action-list;
    }
  }

  notification packet-received {
    description
      "Delivery of incoming packet.";
    uses packet-in;
    container match {
      description
        "Match data that triggered the source of the
         packet-received event.";
      uses match;
    }
  }

  container packet-in-message {
    description
      "Container with the last packet-in reported.
       Useful for basic monitoring.";
    uses packet-in;
    container match {
      description
        "Match data that triggered the source of the
         last packet-received event.";
      uses match;
    }
  }
  container flows {
    description
      "Contains the list of all configured flows.";
    list flow {
      key "id";
      description
        "";
      uses flow;
      container flow-statistics {
        config false;
        description
          "Contains flow counters.";
        leaf packet-count {
          type yang:counter64;
          description
            "Packets matched.";
        }
        leaf byte-count {
          type yang:counter64;
          description
            "Sum of the bytes of all matched packets.";
        }
      }
    }
  }
}
