module opendaylight-match-types {
    namespace "urn:opendaylight:model:match:types";
    prefix "match";

    import ietf-inet-types {prefix inet; revision-date "2013-07-15";}
    import ietf-yang-types {prefix yang; revision-date "2013-07-15";}
    import opendaylight-l2-types {prefix l2t;revision-date "2013-08-27";}
    import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
    import opendaylight-arbitrary-bitmask-fields {prefix mask; revision-date "2016-01-30";}
    import opendaylight-ipv6-arbitrary-bitmask-fields {prefix ipv6-arbitrary-mask; revision-date "2016-02-24";}

    revision "2013-10-26" {
        description "Initial revision of match types";
    }

    grouping "mac-address-filter" {
        leaf address {
            mandatory true;
            type yang:mac-address;
        }
        leaf mask {
            type yang:mac-address;
        }
    }

    grouping "of-metadata" {
        leaf metadata {
            type uint64;
        }

        leaf metadata-mask {
            type uint64;
        }
    }

    grouping packet-type-fields {
        leaf packet-type {
            description
              "Outermost header type of a packet. It's a 4 byte
                value, the 2 most significant bytes are the
                namespace and the next 2 bytes are the type.";
            type uint32;
        }
    }

     /** Match Groupings **/
    grouping "ethernet-match-fields" {
        container ethernet-source {
            description "Ethernet source address.";
            presence "Match field is active and set";
            uses mac-address-filter;
        }
        container ethernet-destination {
            description "Ethernet destination address.";
            presence "Match field is active and set";
            uses mac-address-filter;
        }
        container ethernet-type {
            description "Ethernet frame type.";
            presence "Match field is active and set";

            leaf type {
                mandatory true;
                type l2t:ether-type; // Needs to define that as general model
            }
        }
    }

    grouping "vlan-match-fields" {
        container vlan-id {
            description "VLAN id.";
            presence "Match field is active and set";

            leaf vlan-id-present {
                type boolean;
            }

            leaf vlan-id {
                type l2t:vlan-id;
            }
        }
        leaf vlan-pcp {
            description "VLAN priority.";
            type l2t:vlan-pcp;
        }
    }

    grouping "ip-match-fields" {
        leaf ip-protocol {
                description "IP protocol.";
                type uint8;
        }

        leaf ip-dscp {
            description "IP DSCP (6 bits in ToS field).";
            type inet:dscp;
        }

        leaf ip-ecn {
            description "IP ECN (2 bits in ToS field).";
            type uint8;
        }

        leaf ip-proto {
           description "IP Proto (IPv4 or IPv6 Protocol Number).";
	       type inet:ip-version;
		}
    }

    grouping "ipv4-match-fields" {
        leaf ipv4-source {
            description "IPv4 source address.";
            type inet:ipv4-prefix;
        }

        leaf ipv4-destination {
            description "IPv4 destination address.";
            type inet:ipv4-prefix;
        }

    }

    grouping "ipv6-match-fields" {
        leaf ipv6-source {
            description "IPv6 source address.";
            type inet:ipv6-prefix;
        }

        leaf ipv6-destination {
            description "IPv6 destination address.";
            type inet:ipv6-prefix;
        }

        leaf ipv6-nd-target {
            description "IPv6 target address for neighbour discovery message";
            type inet:ipv6-address;
        }

        container "ipv6-label" {
            leaf ipv6-flabel {
                type inet:ipv6-flow-label;
            }

            leaf flabel-mask {
                type inet:ipv6-flow-label;
            }
        }

        leaf ipv6-nd-sll {
            description "Link layer source address for neighbour discovery message";
            type yang:mac-address;
        }

        leaf ipv6-nd-tll {
            description "Link layer target address for neighbour discovery message";
            type yang:mac-address;
        }

        container "ipv6-ext-header" {
            leaf ipv6-exthdr {
                description "IPv6 Extension Header field";
                type uint16;
            }

            leaf ipv6-exthdr-mask {
                type uint16 {
                  range "0..512";
                }
            }
        }
    }

    grouping "udp-match-fields" {
        leaf udp-source-port {
            description "UDP source port.";
            type inet:port-number;
        }
        leaf udp-source-port-mask {
            description "UDP source port mask.";
            type inet:port-number;
        }
        leaf udp-destination-port {
            description "UDP destination port.";
            type inet:port-number;
        }
        leaf udp-destination-port-mask {
            description "UDP destination port mask.";
            type inet:port-number;
        }
    }

    grouping "protocol-match-fields" {
        leaf mpls-label {
            description "Label in the first MPLS shim header";
            type uint32;
        }

        leaf mpls-tc {
            description "TC in the first MPLS shim header";
            type uint8;
        }

        leaf mpls-bos {
            description "BoS bit in the first MPLS shim header";
            type uint8;
        }

        container "pbb" {
            leaf pbb-isid {
                description "I-SID in the first PBB service instance tag";
                type uint32;
            }

            leaf pbb-mask {
                type uint32 {
                  range "0..16777216";
                }
            }
        }
    }

    grouping "tcp-match-fields" {
        leaf tcp-source-port {
            description "TCP source port.";
            type inet:port-number;
        }
        leaf tcp-source-port-mask {
            description "TCP source port mask.";
            type inet:port-number;
        }
        leaf tcp-destination-port {
            description "TCP destination port.";
            type inet:port-number;
        }
        leaf tcp-destination-port-mask {
            description "TCP destination port mask.";
            type inet:port-number;
        }
    }

    grouping "sctp-match-fields" {
        leaf sctp-source-port {
            description "SCTP source port.";
            type inet:port-number;
        }
        leaf sctp-destination-port {
            description "SCTP destination port.";
            type inet:port-number;
        }
    }

    grouping "icmpv4-match-fields" {
        leaf icmpv4-type {
        description "ICMP type.";
            type uint8; // Define ICMP Type
        }
        description "ICMP code.";
        leaf icmpv4-code {
            type uint8; // Define ICMP Code
        }
    }

    grouping "icmpv6-match-fields" {
        leaf icmpv6-type {
        description "ICMP type.";
            type uint8; // Define ICMP Type
        }
        description "ICMP code.";
        leaf icmpv6-code {
            type uint8; // Define ICMP Code
        }
    }

    grouping "arp-match-fields" {
        leaf arp-op {
            type uint16;
        }

        leaf arp-source-transport-address {
            description "ARP source IPv4 address.";
            type inet:ipv4-prefix;
        }

        leaf arp-target-transport-address {
            description "ARP target IPv4 address.";
            type inet:ipv4-prefix;
        }
        container arp-source-hardware-address {
            description "ARP source hardware address.";
            presence "Match field is active and set";
            uses mac-address-filter;
        }
        container arp-target-hardware-address {
            description "ARP target hardware address.";
            presence "Match field is active and set";
            uses mac-address-filter;
        }
    }

    grouping "tcp-flags-match-fields" {
        leaf tcp-flags {
            description "Tcp flags for match";
            type uint16;
        }
        leaf tcp-flags-mask {
            description "Mask for tcp flags";
            type uint16;
        }
    }

    grouping "tunnel-ipv4-match-fields" {
        leaf tunnel-ipv4-source {
            description "IPv4 source tunnel endpoint address.";
            type inet:ipv4-prefix;
        }
        leaf tunnel-ipv4-destination {
            description "IPv4 destination tunnel endpoint address.";
            type inet:ipv4-prefix;
        }
    }

    grouping match {
        leaf in-port {
            type inv:node-connector-id;
        }

        leaf in-phy-port {
            type inv:node-connector-id;
        }

        container packet-type-match {
            uses packet-type-fields;
        }

        container "metadata" {
            uses of-metadata;
        }

        container "tunnel" {
            leaf tunnel-id {
                description "Metadata associated in the logical port";
                type uint64;
            }

            leaf tunnel-mask {
                type uint64;
            }
        }

        container "ethernet-match" {
            uses "ethernet-match-fields";
        }

        container "vlan-match" {
            uses "vlan-match-fields";
        }

        container "ip-match" {
            uses "ip-match-fields";
        }

        choice layer-3-match {
            case "ipv4-match" {
                uses "ipv4-match-fields";
            }
            case "ipv4-match-arbitrary-bit-mask"{
                uses "mask:ipv4-match-arbitrary-bitmask-fields";
            }
            case "ipv6-match" {
                uses "ipv6-match-fields";
            }
            case "ipv6-match-arbitrary-bit-mask"{
                uses ipv6-arbitrary-mask:ipv6-match-arbitrary-bitmask-fields;
            }
            case "arp-match" {
                uses "arp-match-fields";
            }
            case "tunnel-ipv4-match" {
                uses "tunnel-ipv4-match-fields";
            }
        }

        choice layer-4-match {
            case "udp-match" {
                uses "udp-match-fields";
            }
            case "tcp-match" {
                uses "tcp-match-fields";
            }
            case "sctp-match" {
                uses "sctp-match-fields";
            }
        }

        container "icmpv4-match" {
            uses "icmpv4-match-fields";
        }

        container "icmpv6-match" {
            uses "icmpv6-match-fields";
        }

        container "protocol-match-fields" {
            uses "protocol-match-fields";
        }

        container tcp-flags-match {
            uses "tcp-flags-match-fields";
        }
    }
}