module onf-extensions {
    namespace "urn:opendaylight:openflowplugin:extension:onf";
    prefix "onf-ext";

    import openflow-types {prefix oft; revision-date "2013-07-31";}
    import openflow-protocol {prefix ofproto; revision-date "2013-07-31";}

    revision "2017-01-24" {
        description "Open networking foundation approved extensions definition.";
    }

    // ONF experimenter error codes
    typedef onf-experimenter-error-code {
        description "Error codes for experimenter error type.";
        type enumeration {
            enum ONFERR_ET_UNKNOWN {
                description "Unspecified error.";
                value 2300;
            }
            enum ONFERR_ET_EPERM {
                description "Permissions error.";
                value 2301;
            }
            enum ONFERR_ET_BAD_ID {
                description "Bundle ID doesn’t exist.";
                value 2302;
            }
            enum ONFERR_ET_BUNDLE_EXIST {
                description "Bundle ID already exist.";
                value 2303;
            }
            enum ONFERR_ET_BUNDLE_CLOSED {
                description "Bundle ID is closed.";
                value 2304;
            }
            enum ONFERR_ET_OUT_OF_BUNDLES {
                description "Too many bundles IDs.";
                value 2305;
            }
            enum ONFERR_ET_BAD_TYPE {
                description "Unsupported or unknown message control type.";
                value 2306;
            }
            enum ONFERR_ET_BAD_FLAGS {
                description "Unsupported, unknown, or inconsistent flags.";
                value 2307;
            }
            enum ONFERR_ET_MSG_BAD_LEN {
                description "Length problem in included message.";
                value 2308;
            }
            enum ONFERR_ET_MSG_BAD_XID {
                description "Inconsistent or duplicate XID.";
                value 2309;
            }
            enum ONFERR_ET_MSG_UNSUP {
                description "Unsupported message in this bundle.";
                value 2310;
            }
            enum ONFERR_ET_MSG_CONFLICT {
                description "Unsupported message combination in this bundle.";
                value 2311;
            }
            enum ONFERR_ET_MSG_TOO_MANY {
                description "Can not handle this many messages in bundle.";
                value 2312;
            }
            enum ONFERR_ET_MSG_FAILED {
                description "One message in bundle failed.";
                value 2313;
            }
            enum ONFERR_ET_TIMEOUT {
                description "Bundle is taking too long.";
                value 2314;
            }
            enum ONFERR_ET_BUNDLE_IN_PROGRESS {
                description "Bundle is locking the resource.";
                value 2315;
            }
        }
    }

    // Extension 230 - Bundle Extension
    typedef bundle-id {
        description "Identify the bundle.";
        type uint32;
    }

    typedef bundle-control-type {
        description "Bundle control message type.";
        type enumeration {
            enum ONF_BCT_OPEN_REQUEST {
                value 0;
            }
            enum ONF_BCT_OPEN_REPLY {
                value 1;
            }
            enum ONF_BCT_CLOSE_REQUEST {
                value 2;
            }
            enum ONF_BCT_CLOSE_REPLY {
                value 3;
            }
            enum ONF_BCT_COMMIT_REQUEST {
                value 4;
            }
            enum ONF_BCT_COMMIT_REPLY {
                value 5;
            }
            enum ONF_BCT_DISCARD_REQUEST {
                value 6;
            }
            enum ONF_BCT_DISCARD_REPLY {
                value 7;
            }
        }
    }

    typedef bundle-flags {
        description "Bundle configuration flags.";
        type bits {
            bit atomic {
                description "Execute atomically.";
                position 0;
            }
            bit ordered {
                description "Execute in specified order.";
                position 1;
            }
        }
    }

    typedef bundle-property-type {
        description "Bundle property types.";
        type enumeration {
            enum ONF_ET_BPT_EXPERIMENTER {
                description "Experimenter property.";
                value 65535; //0xFFFF
            }
        }
    }

    grouping bundle-property-grouping {
        description "Container for bundle property.";
        leaf type {
            type bundle-property-type;
        }
        choice bundle-property-entry  {
            case bundle-property-experimenter {
                leaf experimenter {
                     type oft:experimenter-id;
                }
                leaf exp-type {
                     type uint32;
                }
                choice bundle-property-experimenter-data {
                    // to be augmented by vendors
                }
            }
        }
    }

    grouping bundle-common-grouping {
        description "Common fields of bundle messages.";
        leaf bundle-id {
            type bundle-id;
        }
        leaf flags {
            type bundle-flags;
        }
        list bundle-property {
            uses bundle-property-grouping;
        }
    }

    grouping bundle-control-grouping {
        description "ONF_ET_BUNDLE_CONTROL message in OpenFlow Switch Extension 230.";
        uses bundle-common-grouping;
        leaf type {
            type bundle-control-type;
        }
    }

    grouping bundle-add-message-grouping {
        description "ONF_ET_BUNDLE_ADD_MESSAGE in OpenFlow Switch Extension 230.";
        uses bundle-common-grouping;
        choice bundle-inner-message {
            description "Message added to the bundle.";
            case bundle-flow-mod-case {
                container flow-mod-case-data {
                    uses ofproto:flow-mod;
                }
            }
            case bundle-group-mod-case {
                container group-mod-case-data {
                    uses ofproto:group-mod;
                }
            }
            case bundle-port-mod-case {
                container port-mod-case-data {
                    uses ofproto:port-mod;
                }
            }
        }
    }

    augment "/ofproto:experimenter/ofproto:input/ofproto:experimenter-data-of-choice" {
        case bundle-control-onf {
            container onf-control-grouping-data {
                uses bundle-control-grouping;
            }
        }
        case bundle-add-message-onf {
            container onf-add-message-grouping-data {
                uses bundle-add-message-grouping;
            }
        }
    }
}