This commit consists of:
1) Dockerizing the netconf server
2) Update proto2yang to support module imports
3) Provide a set of yang modules derived from the proto files in voltha.
   These files as well as the slight mmodifications to the proto files are
   provided in the experiments/netconf/proto2yang directory
4) Code to automatically pull proto files from voltha into the netconf server,
   compiles them and produce the yang equivalent files.
5) Add a getvoltha netconf API to provide voltha state information (basic at
   this time).  There is potential to make this generic once we experiment
   with additional APIs

Change-Id: I94f3a1f871b8025ad675d5f9b9b626d1be8b8d36
diff --git a/experiments/netconf/proto2yang/adapter.proto b/experiments/netconf/proto2yang/adapter.proto
new file mode 100644
index 0000000..2e16f96
--- /dev/null
+++ b/experiments/netconf/proto2yang/adapter.proto
@@ -0,0 +1,41 @@
+syntax = "proto3";
+
+package voltha;
+
+import "google/protobuf/any.proto";
+import "common.proto";
+import "meta.proto";
+
+
+message AdapterConfig {
+
+    // Common adapter config attributes here
+    LogLevel log_level = 1;
+
+    // Custom (vendor-specific) configuration attributes
+    google.protobuf.Any additional_config = 64;
+
+}
+
+// Adapter (software plugin)
+message Adapter {
+
+    // Unique name of adapter, matching the python packate name under
+    // voltha/adapters.
+    string id = 1 [(access) = READ_ONLY];
+    string vendor = 2 [(access) = READ_ONLY];
+    string version = 3 [(access) = READ_ONLY];
+
+    // Adapter configuration
+    AdapterConfig config = 16;
+
+    // Custom descriptors and custom configuration
+    google.protobuf.Any additional_description = 64 [(access) = READ_ONLY];
+
+    repeated string logical_device_ids = 4;  // Logical devices "owned"
+
+}
+
+message Adapters {
+    repeated Adapter items = 1;
+}
diff --git a/experiments/netconf/proto2yang/adapter_orig.proto b/experiments/netconf/proto2yang/adapter_orig.proto
new file mode 100644
index 0000000..4af54c3
--- /dev/null
+++ b/experiments/netconf/proto2yang/adapter_orig.proto
@@ -0,0 +1,41 @@
+syntax = "proto3";
+
+package voltha;
+
+import "google/protobuf/any.proto";
+import "common.proto";
+import "meta.proto";
+
+
+message AdapterConfig {
+
+    // Common adapter config attributes here
+    LogLevel.LogLevel log_level = 1;
+
+    // Custom (vendor-specific) configuration attributes
+    google.protobuf.Any additional_config = 64;
+
+}
+
+// Adapter (software plugin)
+message Adapter {
+
+    // Unique name of adapter, matching the python packate name under
+    // voltha/adapters.
+    string id = 1 [(access) = READ_ONLY];
+    string vendor = 2 [(access) = READ_ONLY];
+    string version = 3 [(access) = READ_ONLY];
+
+    // Adapter configuration
+    AdapterConfig config = 16;
+
+    // Custom descriptors and custom configuration
+    google.protobuf.Any additional_description = 64 [(access) = READ_ONLY];
+
+    repeated string logical_device_ids = 4;  // Logical devices "owned"
+
+}
+
+message Adapters {
+    repeated Adapter items = 1;
+}
diff --git a/experiments/netconf/proto2yang/adapter_tibit.proto b/experiments/netconf/proto2yang/adapter_tibit.proto
new file mode 100644
index 0000000..ac9f1ec
--- /dev/null
+++ b/experiments/netconf/proto2yang/adapter_tibit.proto
@@ -0,0 +1,24 @@
+syntax = "proto3";
+
+package vendor.x2;
+
+// Vendor specific adapter descriptor data
+message AdapterDescription {
+    string foo = 1;
+    uint32 arg1 = 2;
+    uint32 arg2 = 3;
+    uint32 arg3 = 4;
+    uint32 arg4 = 5;
+    uint32 arg5 = 6;
+    uint32 arg6 = 7;
+}
+
+// Vendor specific adapter configuration data
+message AdapterConfig {
+    uint64 conf1 = 1;
+    uint64 conf2 = 2;
+    uint64 conf3 = 3;
+    uint64 conf4 = 4;
+    uint64 conf5 = 5;
+    repeated string things = 6;
+}
diff --git a/experiments/netconf/proto2yang/addressbook1.proto b/experiments/netconf/proto2yang/addressbook1.proto
new file mode 100644
index 0000000..b90dcdb
--- /dev/null
+++ b/experiments/netconf/proto2yang/addressbook1.proto
@@ -0,0 +1,21 @@
+// See README.txt for information and build instructions.
+
+syntax = "proto3";
+
+package tutorial;
+
+import "addressbook.proto";
+
+// Our address book file is just one of these.
+message AddressBook {
+  repeated Person people = 1;
+  repeated Adapter adapters = 2;
+}
+
+message TestOF {
+//   repeated openflow_13.ofp_group_entry flow_groups = 1;
+   //  repeated openflow_13.ofp_switch_features hell = 1;
+ //    repeated openflow_13.ofp_flow_mod mod = 2;
+  //   repeated openflow_13.ofp_flow_stats stats = 3;
+     repeated ofp_group_entry groupi = 4;
+}
diff --git a/experiments/netconf/proto2yang/common.proto b/experiments/netconf/proto2yang/common.proto
new file mode 100644
index 0000000..0ec8ce3
--- /dev/null
+++ b/experiments/netconf/proto2yang/common.proto
@@ -0,0 +1,71 @@
+syntax = "proto3";
+
+package voltha;
+
+// Convey a resource identifier
+message ID {
+    string id = 1;
+}
+
+
+// Logging verbosity level
+enum LogLevel {
+    DEBUG = 0;
+    INFO = 1;
+    WARNING = 2;
+    ERROR = 3;
+    CRITICAL = 4;
+}
+
+// Administrative State
+enum AdminState {
+
+    // The administrative state of the device is unknown
+    AS_UNKNOWN = 0;
+
+    // The device is pre-provisioned into Voltha, but not contacted by it
+    AS_PREPROVISIONED = 1;
+
+    // The device is enabled for activation and operation
+    AS_ENABLED = 3;
+
+    // The device is disabled and shall not perform its intended forwarding
+    // functions other than being available for re-activation.
+    AS_DISABLED = 2;
+}
+
+// Operational Status
+enum OperStatus {
+
+    // The status of the device is unknown at this point
+    OS_UNKNOWN = 0;
+
+    // The device has been discovered, but not yet activated
+    OS_DISCOVERED = 1;
+
+    // The device is being activated (booted, rebooted, upgraded, etc.)
+    OS_ACTIVATING = 2;
+
+    // Service impacting tests are being conducted
+    OS_TESTING = 3;
+
+    // The device is up and active
+    OS_ACTIVE = 4;
+
+    // The device has failed and cannot fulfill its intended role
+    OS_FAILED = 5;
+}
+
+// Connectivity Status
+enum ConnectStatus {
+
+    // The device connectivity status is unknown
+    CS_UNKNOWN = 0;
+
+    // The device cannot be reached by Voltha
+    CS_UNREACHABLE = 1;
+
+    // There is live communication between device and Voltha
+    CS_REACHABLE = 2;
+}
+
diff --git a/experiments/netconf/proto2yang/common_orig.proto b/experiments/netconf/proto2yang/common_orig.proto
new file mode 100644
index 0000000..1497d56
--- /dev/null
+++ b/experiments/netconf/proto2yang/common_orig.proto
@@ -0,0 +1,81 @@
+syntax = "proto3";
+
+package voltha;
+
+// Convey a resource identifier
+message ID {
+    string id = 1;
+}
+
+message LogLevel {
+
+    // Logging verbosity level
+    enum LogLevel {
+        DEBUG = 0;
+        INFO = 1;
+        WARNING = 2;
+        ERROR = 3;
+        CRITICAL = 4;
+    }
+}
+
+message AdminState {
+
+    // Administrative State
+    enum AdminState {
+
+        // The administrative state of the device is unknown
+        UNKNOWN = 0;
+
+        // The device is pre-provisioned into Voltha, but not contacted by it
+        PREPROVISIONED = 1;
+
+        // The device is enabled for activation and operation
+        ENABLED = 3;
+
+        // The device is disabled and shall not perform its intended forwarding
+        // functions other than being available for re-activation.
+        DISABLED = 2;
+    }
+}
+
+message OperStatus {
+
+    // Operational Status
+    enum OperStatus {
+
+        // The status of the device is unknown at this point
+        UNKNOWN = 0;
+
+        // The device has been discovered, but not yet activated
+        DISCOVERED = 1;
+
+        // The device is being activated (booted, rebooted, upgraded, etc.)
+        ACTIVATING = 2;
+
+        // Service impacting tests are being conducted
+        TESTING = 3;
+
+        // The device is up and active
+        ACTIVE = 4;
+
+        // The device has failed and cannot fulfill its intended role
+        FAILED = 5;
+    }
+}
+
+message ConnectStatus {
+
+    // Connectivity Status
+    enum ConnectStatus {
+
+        // The device connectivity status is unknown
+        UNKNOWN = 0;
+
+        // The device cannot be reached by Voltha
+        UNREACHABLE = 1;
+
+        // There is live communication between device and Voltha
+        REACHABLE = 2;
+    }
+}
diff --git a/experiments/netconf/proto2yang/device.proto b/experiments/netconf/proto2yang/device.proto
new file mode 100644
index 0000000..ac0f7e7
--- /dev/null
+++ b/experiments/netconf/proto2yang/device.proto
@@ -0,0 +1,135 @@
+syntax = "proto3";
+
+package voltha;
+
+import "meta.proto";
+import "google/protobuf/any.proto";
+import "common.proto";
+import "openflow_13.proto";
+
+// A Device Type
+message DeviceType {
+
+    // Unique name for the device type
+    string id = 1;
+
+    // Name of the adapter that handles device type
+    string adapter = 2;
+
+    // Capabilitities
+
+    bool accepts_bulk_flow_update = 3;
+    bool accepts_add_remove_flow_updates = 4;
+
+}
+
+// A plurality of device types
+message DeviceTypes {
+    repeated DeviceType items = 1;
+}
+
+message Port {
+
+    enum PortType {
+        UNKNOWN = 0;
+        ETHERNET_NNI = 1;
+        ETHERNET_UNI = 2;
+        PON_OLT = 3;
+        PON_ONU = 4;
+    }
+
+    uint32 port_no = 1;  // Device-unique port number
+
+    string label = 2;  // Arbitrary port label
+
+    PortType type = 3;  //  Type of port
+
+    AdminState admin_state = 5;
+
+    OperStatus oper_status = 6;
+
+    string device_id = 7;  // Unique .id of device that owns this port
+
+    message PeerPort {
+        string device_id = 1;
+        uint32 port_no = 2;
+    }
+    repeated PeerPort peers = 8;
+
+}
+
+message Ports {
+    repeated Port items = 1;
+}
+
+// A Physical Device instance
+message Device {
+
+    // Voltha's device identifier
+    string id = 1 [(access) = READ_ONLY];
+
+    // Device type, refers to one of the registered device types
+    string type = 2 [(access) = READ_ONLY];
+
+    // Is this device a root device. Each logical switch has one root
+    // device that is associated with the logical flow switch.
+    bool root = 3 [(access) = READ_ONLY];
+
+    // Parent device id, in the device tree (for a root device, the parent_id
+    // is the logical_device.id)
+    string parent_id = 4 [(access) = READ_ONLY];
+    uint32 parent_port_no = 20 [(access) = READ_ONLY];
+
+    // Vendor, version, serial number, etc.
+    string vendor = 5 [(access) = READ_ONLY];
+    string model = 6 [(access) = READ_ONLY];
+    string hardware_version = 7 [(access) = READ_ONLY];
+    string firmware_version = 8 [(access) = READ_ONLY];
+    string software_version = 9 [(access) = READ_ONLY];
+    string serial_number = 10 [(access) = READ_ONLY];
+
+    // Addapter that takes care of device
+    string adapter = 11 [(access) = READ_ONLY];
+
+    // Device contact on vlan (if 0, no vlan)
+    uint32 vlan = 12;
+
+    message ProxyAddress {
+        string device_id = 1;  // Which device to use as proxy to this device
+        uint32 channel_id = 2;  // Sub-address within proxy device
+    };
+
+    oneof address {
+        // Device contact MAC address (format: "xx:xx:xx:xx:xx:xx")
+        string mac_address = 13;
+
+        // Device contact IPv4 address (format: "a.b.c.d" or can use hostname too)
+        string ipv4_address = 14;
+
+        // Device contact IPv6 address using the canonical string form
+        // ("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")
+        string ipv6_address = 15;
+
+        ProxyAddress proxy_device = 19;
+    };
+
+    AdminState admin_state = 16;
+
+    OperStatus oper_status = 17 [(access) = READ_ONLY];
+
+    ConnectStatus connect_status = 18 [(access) = READ_ONLY];
+
+    // TODO additional common attribute here
+
+    // Device type specific attributes
+    google.protobuf.Any custom = 64;
+
+    repeated Port ports = 128  [(child_node) = {key: "port_no"}];
+    openflow_13.Flows flows = 129 [(child_node) = {}];
+    openflow_13.FlowGroups flow_groups = 130 [(child_node) = {}];
+
+}
+
+message Devices {
+    repeated Device items = 1;
+}
diff --git a/experiments/netconf/proto2yang/device_orig.proto b/experiments/netconf/proto2yang/device_orig.proto
new file mode 100644
index 0000000..0a1e9b2
--- /dev/null
+++ b/experiments/netconf/proto2yang/device_orig.proto
@@ -0,0 +1,135 @@
+syntax = "proto3";
+
+package voltha;
+
+import "meta.proto";
+import "google/protobuf/any.proto";
+import "common.proto";
+import "openflow_13.proto";
+
+// A Device Type
+message DeviceType {
+
+    // Unique name for the device type
+    string id = 1;
+
+    // Name of the adapter that handles device type
+    string adapter = 2;
+
+    // Capabilitities
+
+    bool accepts_bulk_flow_update = 3;
+    bool accepts_add_remove_flow_updates = 4;
+
+}
+
+// A plurality of device types
+message DeviceTypes {
+    repeated DeviceType items = 1;
+}
+
+message Port {
+
+    enum PortType {
+        UNKNOWN = 0;
+        ETHERNET_NNI = 1;
+        ETHERNET_UNI = 2;
+        PON_OLT = 3;
+        PON_ONU = 4;
+    }
+
+    uint32 port_no = 1;  // Device-unique port number
+
+    string label = 2;  // Arbitrary port label
+
+    PortType type = 3;  //  Type of port
+
+    AdminState.AdminState admin_state = 5;
+
+    OperStatus.OperStatus oper_status = 6;
+
+    string device_id = 7;  // Unique .id of device that owns this port
+
+    message PeerPort {
+        string device_id = 1;
+        uint32 port_no = 2;
+    }
+    repeated PeerPort peers = 8;
+
+}
+
+message Ports {
+    repeated Port items = 1;
+}
+
+// A Physical Device instance
+message Device {
+
+    // Voltha's device identifier
+    string id = 1 [(access) = READ_ONLY];
+
+    // Device type, refers to one of the registered device types
+    string type = 2 [(access) = READ_ONLY];
+
+    // Is this device a root device. Each logical switch has one root
+    // device that is associated with the logical flow switch.
+    bool root = 3 [(access) = READ_ONLY];
+
+    // Parent device id, in the device tree (for a root device, the parent_id
+    // is the logical_device.id)
+    string parent_id = 4 [(access) = READ_ONLY];
+    uint32 parent_port_no = 20 [(access) = READ_ONLY];
+
+    // Vendor, version, serial number, etc.
+    string vendor = 5 [(access) = READ_ONLY];
+    string model = 6 [(access) = READ_ONLY];
+    string hardware_version = 7 [(access) = READ_ONLY];
+    string firmware_version = 8 [(access) = READ_ONLY];
+    string software_version = 9 [(access) = READ_ONLY];
+    string serial_number = 10 [(access) = READ_ONLY];
+
+    // Addapter that takes care of device
+    string adapter = 11 [(access) = READ_ONLY];
+
+    // Device contact on vlan (if 0, no vlan)
+    uint32 vlan = 12;
+
+    message ProxyAddress {
+        string device_id = 1;  // Which device to use as proxy to this device
+        uint32 channel_id = 2;  // Sub-address within proxy device
+    };
+
+    oneof address {
+        // Device contact MAC address (format: "xx:xx:xx:xx:xx:xx")
+        string mac_address = 13;
+
+        // Device contact IPv4 address (format: "a.b.c.d" or can use hostname too)
+        string ipv4_address = 14;
+
+        // Device contact IPv6 address using the canonical string form
+        // ("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")
+        string ipv6_address = 15;
+
+        ProxyAddress proxy_device = 19;
+    };
+
+    AdminState.AdminState admin_state = 16;
+
+    OperStatus.OperStatus oper_status = 17 [(access) = READ_ONLY];
+
+    ConnectStatus.ConnectStatus connect_status = 18 [(access) = READ_ONLY];
+
+    // TODO additional common attribute here
+
+    // Device type specific attributes
+    google.protobuf.Any custom = 64;
+
+    repeated Port ports = 128  [(child_node) = {key: "port_no"}];
+    openflow_13.Flows flows = 129 [(child_node) = {}];
+    openflow_13.FlowGroups flow_groups = 130 [(child_node) = {}];
+
+}
+
+message Devices {
+    repeated Device items = 1;
+}
diff --git a/experiments/netconf/proto2yang/health.proto b/experiments/netconf/proto2yang/health.proto
new file mode 100644
index 0000000..19383a9
--- /dev/null
+++ b/experiments/netconf/proto2yang/health.proto
@@ -0,0 +1,34 @@
+syntax = "proto3";
+
+package voltha;
+
+import "google/api/annotations.proto";
+import "google/protobuf/empty.proto";
+import "meta.proto";
+
+// Encode health status of a Voltha instance
+message HealthStatus {
+
+    // Health states
+    enum HealthState {
+        HEALTHY = 0;  // The instance is healthy
+        OVERLOADED = 1;  // The instance is overloaded, decrease query rate
+        DYING = 2;  // The instance is in a critical condition, do not use it
+    }
+
+    // Current state of health of this Voltha instance
+    HealthState state = 1 [(access) = READ_ONLY];
+}
+
+// Health related services
+service HealthService {
+
+    // Return current health status of a Voltha instance
+    rpc GetHealthStatus(google.protobuf.Empty) returns (HealthStatus) {
+        option (google.api.http) = {
+            get: "/health"
+        };
+    }
+
+}
+
diff --git a/experiments/netconf/proto2yang/ietf-adapter.yang b/experiments/netconf/proto2yang/ietf-adapter.yang
new file mode 100644
index 0000000..42ef6e3
--- /dev/null
+++ b/experiments/netconf/proto2yang/ietf-adapter.yang
@@ -0,0 +1,105 @@
+
+module ietf-adapter {
+
+
+    namespace "urn:opencord:params:xml:ns:voltha:ietf-adapter";
+    prefix adapter;
+
+    import ietf-common { prefix common ; }
+    import ietf-any { prefix any ; }
+
+    organization "CORD";
+    contact
+        " Any name";
+
+    description
+        "";
+
+    revision "2016-11-15" {
+        description "Initial revision.";
+        reference "reference";
+    }
+
+
+    grouping AdapterConfig {
+        description
+            "";
+        leaf log_level {
+            type  common:LogLevel;
+
+            description
+                "Common adapter config attributes here";
+        }
+
+        container additional_config {
+            uses  any:Any;
+
+            description
+                "Custom (vendor-specific) configuration attributes";
+        }
+
+    }
+
+    grouping Adapter {
+        description
+            "Adapter (software plugin)";
+        leaf id {
+            type  string; 
+            description
+                "Unique name of adapter, matching the python packate name under
+ voltha adapters.";
+        }
+
+        leaf vendor {
+            type  string; 
+            description
+                "";
+        }
+
+        leaf version {
+            type  string; 
+            description
+                "";
+        }
+
+        container config {
+            uses  AdapterConfig;
+
+            description
+                "Adapter configuration";
+        }
+
+        container additional_description {
+            uses  any:Any;
+
+            description
+                "Custom descriptors and custom configuration";
+        }
+
+        list logical_device_ids {
+            key "logical_device_ids";
+            leaf logical_device_ids {
+                type  string; 
+                description
+                    "Logical devices  owned ";
+            }
+            description
+                "Logical devices  owned ";
+        }
+
+    }
+
+    grouping Adapters {
+        description
+            "";
+        list items {
+            key "id";
+            uses  Adapter;
+
+            description
+                "";
+        }
+
+    }
+
+}
\ No newline at end of file
diff --git a/experiments/netconf/proto2yang/ietf-annotations.yang b/experiments/netconf/proto2yang/ietf-annotations.yang
new file mode 100644
index 0000000..8af4415
--- /dev/null
+++ b/experiments/netconf/proto2yang/ietf-annotations.yang
@@ -0,0 +1,22 @@
+
+module ietf-annotations {
+
+
+    namespace "urn:opencord:params:xml:ns:voltha:ietf-annotations";
+    prefix annotations;
+
+
+    organization "CORD";
+    contact
+        " Any name";
+
+    description
+        "";
+
+    revision "2016-11-15" {
+        description "Initial revision.";
+        reference "reference";
+    }
+
+
+}
\ No newline at end of file
diff --git a/experiments/netconf/proto2yang/ietf-any.yang b/experiments/netconf/proto2yang/ietf-any.yang
new file mode 100644
index 0000000..bf318af
--- /dev/null
+++ b/experiments/netconf/proto2yang/ietf-any.yang
@@ -0,0 +1,127 @@
+
+module ietf-any {
+
+
+    namespace "urn:opencord:params:xml:ns:voltha:ietf-any";
+    prefix any;
+
+
+    organization "CORD";
+    contact
+        " Any name";
+
+    description
+        "";
+
+    revision "2016-11-15" {
+        description "Initial revision.";
+        reference "reference";
+    }
+
+
+    grouping Any {
+        description
+            "`Any` contains an arbitrary serialized protocol buffer message along with a
+ URL that describes the type of the serialized message.
+
+ Protobuf library provides support to pack unpack Any values in the form
+ of utility functions or additional generated methods of the Any type.
+
+ Example 1: Pack and unpack a message in C++.
+
+     Foo foo = ...;
+     Any any;
+     any.PackFrom(foo);
+     ...
+     if (any.UnpackTo(&foo))  
+       ...
+      
+
+ Example 2: Pack and unpack a message in Java.
+
+     Foo foo = ...;
+     Any any = Any.pack(foo);
+     ...
+     if (any.is(Foo.class))  
+       foo = any.unpack(Foo.class);
+      
+
+  Example 3: Pack and unpack a message in Python.
+
+     foo = Foo(...)
+     any = Any()
+     any.Pack(foo)
+     ...
+     if any.Is(Foo.DESCRIPTOR):
+       any.Unpack(foo)
+       ...
+
+ The pack methods provided by protobuf library will by default use
+ 'type.googleapis.com full.type.name' as the type URL and the unpack
+ methods only use the fully qualified type name after the last ' '
+ in the type URL, for example  foo.bar.com x y.z  will yield type
+ name  y.z .
+
+
+ JSON
+ ====
+ The JSON representation of an `Any` value uses the regular
+ representation of the deserialized, embedded message, with an
+ additional field `@type` which contains the type URL. Example:
+
+     package google.profile;
+     message Person  
+       string first_name = 1;
+       string last_name = 2;
+      
+
+      
+        @type :  type.googleapis.com google.profile.Person ,
+        firstName : <string>,
+        lastName : <string>
+      
+
+ If the embedded message type is well-known and has a custom JSON
+ representation, that representation will be embedded adding a field
+ `value` which holds the custom JSON in addition to the `@type`
+ field. Example (for message  google.protobuf.Duration   ):
+
+      
+        @type :  type.googleapis.com google.protobuf.Duration ,
+        value :  1.212s 
+      ";
+        leaf type_url {
+            type  string; 
+            description
+                "A URL resource name whose content describes the type of the
+ serialized protocol buffer message.
+
+ For URLs which use the scheme `http`, `https`, or no scheme, the
+ following restrictions and interpretations apply:
+
+   If no scheme is provided, `https` is assumed.
+   The last segment of the URL's path must represent the fully
+   qualified name of the type (as in `path google.protobuf.Duration`).
+   The name should be in a canonical form (e.g., leading  .  is
+   not accepted).
+   An HTTP GET on the URL must yield a  google.protobuf.Type   
+   value in binary format, or produce an error.
+   Applications are allowed to cache lookup results based on the
+   URL, or have them precompiled into a binary to avoid any
+   lookup. Therefore, binary compatibility needs to be preserved
+   on changes to types. (Use versioned type names to manage
+   breaking changes.)
+
+ Schemes other than `http`, `https` (or the empty scheme) might be
+ used with implementation specific semantics.";
+        }
+
+        leaf value {
+            type  binary; 
+            description
+                "Must be a valid serialized protocol buffer of the above specified type.";
+        }
+
+    }
+
+}
\ No newline at end of file
diff --git a/experiments/netconf/proto2yang/ietf-common.yang b/experiments/netconf/proto2yang/ietf-common.yang
new file mode 100644
index 0000000..b2f6fab
--- /dev/null
+++ b/experiments/netconf/proto2yang/ietf-common.yang
@@ -0,0 +1,111 @@
+
+module ietf-common {
+
+
+    namespace "urn:opencord:params:xml:ns:voltha:ietf-common";
+    prefix common;
+
+
+    organization "CORD";
+    contact
+        " Any name";
+
+    description
+        "";
+
+    revision "2016-11-15" {
+        description "Initial revision.";
+        reference "reference";
+    }
+
+    typedef LogLevel {
+        type enumeration {
+            enum DEBUG {
+                description "";
+            }
+            enum INFO {
+                description "";
+            }
+            enum WARNING {
+                description "";
+            }
+            enum ERROR {
+                description "";
+            }
+            enum CRITICAL {
+                description "";
+            }
+        }
+        description
+            "Logging verbosity level";
+    }
+    typedef AdminState {
+        type enumeration {
+            enum AS_UNKNOWN {
+                description "";
+            }
+            enum AS_PREPROVISIONED {
+                description "";
+            }
+            enum AS_ENABLED {
+                description "";
+            }
+            enum AS_DISABLED {
+                description "";
+            }
+        }
+        description
+            "Administrative State";
+    }
+    typedef OperStatus {
+        type enumeration {
+            enum OS_UNKNOWN {
+                description "";
+            }
+            enum OS_DISCOVERED {
+                description "";
+            }
+            enum OS_ACTIVATING {
+                description "";
+            }
+            enum OS_TESTING {
+                description "";
+            }
+            enum OS_ACTIVE {
+                description "";
+            }
+            enum OS_FAILED {
+                description "";
+            }
+        }
+        description
+            "Operational Status";
+    }
+    typedef ConnectStatus {
+        type enumeration {
+            enum CS_UNKNOWN {
+                description "";
+            }
+            enum CS_UNREACHABLE {
+                description "";
+            }
+            enum CS_REACHABLE {
+                description "";
+            }
+        }
+        description
+            "Connectivity Status";
+    }
+
+    grouping ID {
+        description
+            "Convey a resource identifier";
+        leaf id {
+            type  string; 
+            description
+                "";
+        }
+
+    }
+
+}
\ No newline at end of file
diff --git a/experiments/netconf/proto2yang/ietf-descriptor.yang b/experiments/netconf/proto2yang/ietf-descriptor.yang
new file mode 100644
index 0000000..487f100
--- /dev/null
+++ b/experiments/netconf/proto2yang/ietf-descriptor.yang
@@ -0,0 +1,1331 @@
+
+module ietf-descriptor {
+
+
+    namespace "urn:opencord:params:xml:ns:voltha:ietf-descriptor";
+    prefix descriptor;
+
+
+    organization "CORD";
+    contact
+        " Any name";
+
+    description
+        "";
+
+    revision "2016-11-15" {
+        description "Initial revision.";
+        reference "reference";
+    }
+
+
+    container FileDescriptorSet {
+        description
+            "The protocol compiler can output a FileDescriptorSet containing the .proto
+ files it parses.";
+        list file {
+            key "name";
+            uses  FileDescriptorProto;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping FileDescriptorProto {
+        description
+            "Describes a complete .proto file.";
+        leaf name {
+            type  string; 
+            description
+                "file name, relative to root of source tree";
+        }
+
+        leaf package {
+            type  string; 
+            description
+                "e.g.  foo ,  foo.bar , etc.";
+        }
+
+        list dependency {
+            key "dependency";
+            leaf dependency {
+                type  string; 
+                description
+                    "Names of files imported by this file.";
+            }
+            description
+                "Names of files imported by this file.";
+        }
+
+        list public_dependency {
+            key "public_dependency";
+            leaf public_dependency {
+                type  int32; 
+                description
+                    "Indexes of the public imported files in the dependency list above.";
+            }
+            description
+                "Indexes of the public imported files in the dependency list above.";
+        }
+
+        list weak_dependency {
+            key "weak_dependency";
+            leaf weak_dependency {
+                type  int32; 
+                description
+                    "Indexes of the weak imported files in the dependency list.
+ For Google-internal migration only. Do not use.";
+            }
+            description
+                "Indexes of the weak imported files in the dependency list.
+ For Google-internal migration only. Do not use.";
+        }
+
+        list message_type {
+            key "name";
+            uses  DescriptorProto;
+
+            description
+                "All top-level definitions in this file.";
+        }
+
+        list enum_type {
+            key "name";
+            uses  EnumDescriptorProto;
+
+            description
+                "";
+        }
+
+        list service {
+            key "name";
+            uses  ServiceDescriptorProto;
+
+            description
+                "";
+        }
+
+        list extension {
+            key "name";
+            uses  FieldDescriptorProto;
+
+            description
+                "";
+        }
+
+        container options {
+            uses  FileOptions;
+
+            description
+                "";
+        }
+
+        container source_code_info {
+            uses  SourceCodeInfo;
+
+            description
+                "This field contains optional information about the original source code.
+ You may safely remove this entire field without harming runtime
+ functionality of the descriptors -- the information is needed only by
+ development tools.";
+        }
+
+        leaf syntax {
+            type  string; 
+            description
+                "The syntax of the proto file.
+ The supported values are  proto2  and  proto3 .";
+        }
+
+    }
+
+    grouping DescriptorProto {
+        description
+            "Describes a message type.";
+        leaf name {
+            type  string; 
+            description
+                "";
+        }
+
+        list field {
+            key "name";
+            uses  FieldDescriptorProto;
+
+            description
+                "";
+        }
+
+        list extension {
+            key "name";
+            uses  FieldDescriptorProto;
+
+            description
+                "";
+        }
+
+        list nested_type {
+            key "name";
+            uses  DescriptorProto;
+
+            description
+                "";
+        }
+
+        list enum_type {
+            key "name";
+            uses  EnumDescriptorProto;
+
+            description
+                "";
+        }
+
+
+        list oneof_decl {
+            key "name";
+            uses  OneofDescriptorProto;
+
+            description
+                "";
+        }
+
+        container options {
+            uses  MessageOptions;
+
+            description
+                "";
+        }
+
+
+        list reserved_name {
+            key "reserved_name";
+            leaf reserved_name {
+                type  string; 
+                description
+                    "Reserved field names, which may not be used by fields in the same message.
+ A given name may only be reserved once.";
+            }
+            description
+                "Reserved field names, which may not be used by fields in the same message.
+ A given name may only be reserved once.";
+        }
+
+        grouping ExtensionRange {
+            description
+                "";
+            leaf start {
+                type  int32; 
+                description
+                    "";
+            }
+    
+            leaf end {
+                type  int32; 
+                description
+                    "";
+            }
+    
+        }
+    
+        grouping ReservedRange {
+            description
+                "Range of reserved tag numbers. Reserved tag numbers may not be used by
+     fields or extension ranges in the same message. Reserved ranges may
+     not overlap.";
+            leaf start {
+                type  int32; 
+                description
+                    "Inclusive.";
+            }
+    
+            leaf end {
+                type  int32; 
+                description
+                    "Exclusive.";
+            }
+    
+        }
+    
+    }
+
+    grouping FieldDescriptorProto {
+        description
+            "Describes a field within a message.";
+        leaf name {
+            type  string; 
+            description
+                "";
+        }
+
+        leaf number {
+            type  int32; 
+            description
+                "";
+        }
+
+        leaf label {
+            type  Label; 
+            description
+                "";
+        }
+
+        leaf type {
+            type  Type; 
+            description
+                "If type_name is set, this need not be set.  If both this and type_name
+ are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.";
+        }
+
+        leaf type_name {
+            type  string; 
+            description
+                "For message and enum types, this is the name of the type.  If the name
+ starts with a '.', it is fully-qualified.  Otherwise, C++-like scoping
+ rules are used to find the type (i.e. first the nested types within this
+ message are searched, then within the parent, on up to the root
+ namespace).";
+        }
+
+        leaf extendee {
+            type  string; 
+            description
+                "For extensions, this is the name of the type being extended.  It is
+ resolved in the same manner as type_name.";
+        }
+
+        leaf default_value {
+            type  string; 
+            description
+                "For numeric types, contains the original text representation of the value.
+ For booleans,  true  or  false .
+ For strings, contains the default text contents (not escaped in any way).
+ For bytes, contains the C escaped value.  All bytes >= 128 are escaped.
+ TODO(kenton):  Base-64 encode?";
+        }
+
+        leaf oneof_index {
+            type  int32; 
+            description
+                "If set, gives the index of a oneof in the containing type's oneof_decl
+ list.  This field is a member of that oneof.";
+        }
+
+        leaf json_name {
+            type  string; 
+            description
+                "JSON name of this field. The value is set by protocol compiler. If the
+ user has set a  json_name  option on this field, that option's value
+ will be used. Otherwise, it's deduced from the field's name by converting
+ it to camelCase.";
+        }
+
+        container options {
+            uses  FieldOptions;
+
+            description
+                "";
+        }
+
+        typedef Type {
+            type enumeration {
+                enum TYPE_DOUBLE {
+                    description "";
+                }
+                enum TYPE_FLOAT {
+                    description "";
+                }
+                enum TYPE_INT64 {
+                    description "";
+                }
+                enum TYPE_UINT64 {
+                    description "";
+                }
+                enum TYPE_INT32 {
+                    description "";
+                }
+                enum TYPE_FIXED64 {
+                    description "";
+                }
+                enum TYPE_FIXED32 {
+                    description "";
+                }
+                enum TYPE_BOOL {
+                    description "";
+                }
+                enum TYPE_STRING {
+                    description "";
+                }
+                enum TYPE_GROUP {
+                    description "";
+                }
+                enum TYPE_MESSAGE {
+                    description "";
+                }
+                enum TYPE_BYTES {
+                    description "";
+                }
+                enum TYPE_UINT32 {
+                    description "";
+                }
+                enum TYPE_ENUM {
+                    description "";
+                }
+                enum TYPE_SFIXED32 {
+                    description "";
+                }
+                enum TYPE_SFIXED64 {
+                    description "";
+                }
+                enum TYPE_SINT32 {
+                    description "";
+                }
+                enum TYPE_SINT64 {
+                    description "";
+                }
+            }
+            description
+                "";
+        }
+
+        typedef Label {
+            type enumeration {
+                enum LABEL_OPTIONAL {
+                    description "";
+                }
+                enum LABEL_REQUIRED {
+                    description "";
+                }
+                enum LABEL_REPEATED {
+                    description "";
+                }
+            }
+            description
+                "";
+        }
+
+    }
+
+    grouping OneofDescriptorProto {
+        description
+            "Describes a oneof.";
+        leaf name {
+            type  string; 
+            description
+                "";
+        }
+
+        container options {
+            uses  OneofOptions;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping EnumDescriptorProto {
+        description
+            "Describes an enum type.";
+        leaf name {
+            type  string; 
+            description
+                "";
+        }
+
+        list value {
+            key "name";
+            uses  EnumValueDescriptorProto;
+
+            description
+                "";
+        }
+
+        container options {
+            uses  EnumOptions;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping EnumValueDescriptorProto {
+        description
+            "Describes a value within an enum.";
+        leaf name {
+            type  string; 
+            description
+                "";
+        }
+
+        leaf number {
+            type  int32; 
+            description
+                "";
+        }
+
+        container options {
+            uses  EnumValueOptions;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping ServiceDescriptorProto {
+        description
+            "Describes a service.";
+        leaf name {
+            type  string; 
+            description
+                "";
+        }
+
+        list method {
+            key "name";
+            uses  MethodDescriptorProto;
+
+            description
+                "";
+        }
+
+        container options {
+            uses  ServiceOptions;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping MethodDescriptorProto {
+        description
+            "Describes a method of a service.";
+        leaf name {
+            type  string; 
+            description
+                "";
+        }
+
+        leaf input_type {
+            type  string; 
+            description
+                "Input and output type names.  These are resolved in the same way as
+ FieldDescriptorProto.type_name, but must refer to a message type.";
+        }
+
+        leaf output_type {
+            type  string; 
+            description
+                "";
+        }
+
+        container options {
+            uses  MethodOptions;
+
+            description
+                "";
+        }
+
+        leaf client_streaming {
+            type  boolean; 
+            description
+                "Identifies if client streams multiple client messages";
+        }
+
+        leaf server_streaming {
+            type  boolean; 
+            description
+                "Identifies if server streams multiple server messages";
+        }
+
+    }
+
+    grouping FileOptions {
+        description
+            "===================================================================
+ Options
+Each of the definitions above may have  options  attached.  These are
+ just annotations which may cause code to be generated slightly differently
+ or may contain hints for code that manipulates protocol messages.
+
+ Clients may define custom options as extensions of the  Options messages.
+ These extensions may not yet be known at parsing time, so the parser cannot
+ store the values in them.  Instead it stores them in a field in the  Options
+ message called uninterpreted_option. This field must have the same name
+ across all  Options messages. We then use this field to populate the
+ extensions when we build a descriptor, at which point all protos have been
+ parsed and so all extensions are known.
+
+ Extension numbers for custom options may be chosen as follows:
+   For options which will only be used within a single application or
+   organization, or for experimental options, use field numbers 50000
+   through 99999.  It is up to you to ensure that you do not use the
+   same number for multiple options.
+   For options which will be published and used publicly by multiple
+   independent entities, e-mail protobuf-global-extension-registry@google.com
+   to reserve extension numbers. Simply provide your project name (e.g.
+   Objective-C plugin) and your project website (if available) -- there's no
+   need to explain how you intend to use them. Usually you only need one
+   extension number. You can declare multiple options with only one extension
+   number by putting them in a sub-message. See the Custom Options section of
+   the docs for examples:
+   https:  developers.google.com protocol-buffers docs proto#options
+   If this turns out to be popular, a web service will be set up
+   to automatically assign option numbers.";
+        leaf java_package {
+            type  string; 
+            description
+                "Sets the Java package where classes generated from this .proto will be
+ placed.  By default, the proto package is used, but this is often
+ inappropriate because proto packages do not normally start with backwards
+ domain names.";
+        }
+
+        leaf java_outer_classname {
+            type  string; 
+            description
+                "If set, all the classes from the .proto file are wrapped in a single
+ outer class with the given name.  This applies to both Proto1
+ (equivalent to the old  --one_java_file  option) and Proto2 (where
+ a .proto always translates to a single class, but you may want to
+ explicitly choose the class name).";
+        }
+
+        leaf java_multiple_files {
+            type  boolean; 
+            description
+                "If set true, then the Java code generator will generate a separate .java
+ file for each top-level message, enum, and service defined in the .proto
+ file.  Thus, these types will  not  be nested inside the outer class
+ named by java_outer_classname.  However, the outer class will still be
+ generated to contain the file's getDescriptor() method as well as any
+ top-level extensions defined in the file.";
+        }
+
+        leaf java_generate_equals_and_hash {
+            type  boolean; 
+            description
+                "If set true, then the Java code generator will generate equals() and
+ hashCode() methods for all messages defined in the .proto file.
+ This increases generated code size, potentially substantially for large
+ protos, which may harm a memory-constrained application.
+ - In the full runtime this is a speed optimization, as the
+ AbstractMessage base class includes reflection-based implementations of
+ these methods.
+ - In the lite runtime, setting this option changes the semantics of
+ equals() and hashCode() to more closely match those of the full runtime;
+ the generated methods compute their results based on field values rather
+ than object identity. (Implementations should not assume that hashcodes
+ will be consistent across runtimes or versions of the protocol compiler.)";
+        }
+
+        leaf java_string_check_utf8 {
+            type  boolean; 
+            description
+                "If set true, then the Java2 code generator will generate code that
+ throws an exception whenever an attempt is made to assign a non-UTF-8
+ byte sequence to a string field.
+ Message reflection will do the same.
+ However, an extension field still accepts non-UTF-8 byte sequences.
+ This option has no effect on when used with the lite runtime.";
+        }
+
+        leaf optimize_for {
+            type  OptimizeMode; 
+            description
+                "";
+        }
+
+        leaf go_package {
+            type  string; 
+            description
+                "Sets the Go package where structs generated from this .proto will be
+ placed. If omitted, the Go package will be derived from the following:
+   - The basename of the package import path, if provided.
+   - Otherwise, the package statement in the .proto file, if present.
+   - Otherwise, the basename of the .proto file, without extension.";
+        }
+
+        leaf cc_generic_services {
+            type  boolean; 
+            description
+                "Should generic services be generated in each language?   Generic  services
+ are not specific to any particular RPC system.  They are generated by the
+ main code generators in each language (without additional plugins).
+ Generic services were the only kind of service generation supported by
+ early versions of google.protobuf.
+
+ Generic services are now considered deprecated in favor of using plugins
+ that generate code specific to your particular RPC system.  Therefore,
+ these default to false.  Old code which depends on generic services should
+ explicitly set them to true.";
+        }
+
+        leaf java_generic_services {
+            type  boolean; 
+            description
+                "";
+        }
+
+        leaf py_generic_services {
+            type  boolean; 
+            description
+                "";
+        }
+
+        leaf deprecated {
+            type  boolean; 
+            description
+                "Is this file deprecated?
+ Depending on the target platform, this can emit Deprecated annotations
+ for everything in the file, or it will be completely ignored; in the very
+ least, this is a formalization for deprecating files.";
+        }
+
+        leaf cc_enable_arenas {
+            type  boolean; 
+            description
+                "Enables the use of arenas for the proto messages in this file. This applies
+ only to generated classes for C++.";
+        }
+
+        leaf objc_class_prefix {
+            type  string; 
+            description
+                "Sets the objective c class prefix which is prepended to all objective c
+ generated classes from this .proto. There is no default.";
+        }
+
+        leaf csharp_namespace {
+            type  string; 
+            description
+                "Namespace for generated classes; defaults to the package.";
+        }
+
+        list uninterpreted_option {
+            key "identifier_value";
+            uses  UninterpretedOption;
+
+            description
+                "The parser stores options it doesn't recognize here. See above.";
+        }
+
+        typedef OptimizeMode {
+            type enumeration {
+                enum SPEED {
+                    description "";
+                }
+                enum CODE_SIZE {
+                    description "";
+                }
+                enum LITE_RUNTIME {
+                    description "";
+                }
+            }
+            description
+                "Generated classes can be optimized for speed or code size.";
+        }
+
+    }
+
+    grouping MessageOptions {
+        description
+            "";
+        leaf message_set_wire_format {
+            type  boolean; 
+            description
+                "Set true to use the old proto1 MessageSet wire format for extensions.
+ This is provided for backwards-compatibility with the MessageSet wire
+ format.  You should not use this for any other reason:  It's less
+ efficient, has fewer features, and is more complicated.
+
+ The message must be defined exactly as follows:
+   message Foo  
+     option message_set_wire_format = true;
+     extensions 4 to max;
+    
+ Note that the message cannot have any defined fields; MessageSets only
+ have extensions.
+
+ All extensions of your type must be singular messages; e.g. they cannot
+ be int32s, enums, or repeated messages.
+
+ Because this is an option, the above two restrictions are not enforced by
+ the protocol compiler.";
+        }
+
+        leaf no_standard_descriptor_accessor {
+            type  boolean; 
+            description
+                "Disables the generation of the standard  descriptor()  accessor, which can
+ conflict with a field of the same name.  This is meant to make migration
+ from proto1 easier; new code should avoid fields named  descriptor .";
+        }
+
+        leaf deprecated {
+            type  boolean; 
+            description
+                "Is this message deprecated?
+ Depending on the target platform, this can emit Deprecated annotations
+ for the message, or it will be completely ignored; in the very least,
+ this is a formalization for deprecating messages.";
+        }
+
+        leaf map_entry {
+            type  boolean; 
+            description
+                "Whether the message is an automatically generated map entry type for the
+ maps field.
+
+ For maps fields:
+     map<KeyType, ValueType> map_field = 1;
+ The parsed descriptor looks like:
+     message MapFieldEntry  
+         option map_entry = true;
+         optional KeyType key = 1;
+         optional ValueType value = 2;
+      
+     repeated MapFieldEntry map_field = 1;
+
+ Implementations may choose not to generate the map_entry=true message, but
+ use a native map in the target language to hold the keys and values.
+ The reflection APIs in such implementions still need to work as
+ if the field is a repeated message field.
+
+ NOTE: Do not set the option in .proto files. Always use the maps syntax
+ instead. The option should only be implicitly set by the proto compiler
+ parser.";
+        }
+
+        list uninterpreted_option {
+            key "identifier_value";
+            uses  UninterpretedOption;
+
+            description
+                "The parser stores options it doesn't recognize here. See above.";
+        }
+
+    }
+
+    grouping FieldOptions {
+        description
+            "";
+        leaf ctype {
+            type  CType; 
+            description
+                "The ctype option instructs the C++ code generator to use a different
+ representation of the field than it normally would.  See the specific
+ options below.  This option is not yet implemented in the open source
+ release -- sorry, we'll try to include it in a future version!";
+        }
+
+        leaf packed {
+            type  boolean; 
+            description
+                "The packed option can be enabled for repeated primitive fields to enable
+ a more efficient representation on the wire. Rather than repeatedly
+ writing the tag and type for each element, the entire array is encoded as
+ a single length-delimited blob. In proto3, only explicit setting it to
+ false will avoid using packed encoding.";
+        }
+
+        leaf jstype {
+            type  JSType; 
+            description
+                "The jstype option determines the JavaScript type used for values of the
+ field.  The option is permitted only for 64 bit integral and fixed types
+ (int64, uint64, sint64, fixed64, sfixed64).  By default these types are
+ represented as JavaScript strings.  This avoids loss of precision that can
+ happen when a large value is converted to a floating point JavaScript
+ numbers.  Specifying JS_NUMBER for the jstype causes the generated
+ JavaScript code to use the JavaScript  number  type instead of strings.
+ This option is an enum to permit additional types to be added,
+ e.g. goog.math.Integer.";
+        }
+
+        leaf lazy {
+            type  boolean; 
+            description
+                "Should this field be parsed lazily?  Lazy applies only to message-type
+ fields.  It means that when the outer message is initially parsed, the
+ inner message's contents will not be parsed but instead stored in encoded
+ form.  The inner message will actually be parsed when it is first accessed.
+
+ This is only a hint.  Implementations are free to choose whether to use
+ eager or lazy parsing regardless of the value of this option.  However,
+ setting this option true suggests that the protocol author believes that
+ using lazy parsing on this field is worth the additional bookkeeping
+ overhead typically needed to implement it.
+
+ This option does not affect the public interface of any generated code;
+ all method signatures remain the same.  Furthermore, thread-safety of the
+ interface is not affected by this option; const methods remain safe to
+ call from multiple threads concurrently, while non-const methods continue
+ to require exclusive access.
+
+
+ Note that implementations may choose not to check required fields within
+ a lazy sub-message.  That is, calling IsInitialized() on the outher message
+ may return true even if the inner message has missing required fields.
+ This is necessary because otherwise the inner message would have to be
+ parsed in order to perform the check, defeating the purpose of lazy
+ parsing.  An implementation which chooses not to check required fields
+ must be consistent about it.  That is, for any particular sub-message, the
+ implementation must either  always  check its required fields, or  never 
+ check its required fields, regardless of whether or not the message has
+ been parsed.";
+        }
+
+        leaf deprecated {
+            type  boolean; 
+            description
+                "Is this field deprecated?
+ Depending on the target platform, this can emit Deprecated annotations
+ for accessors, or it will be completely ignored; in the very least, this
+ is a formalization for deprecating fields.";
+        }
+
+        leaf weak {
+            type  boolean; 
+            description
+                "For Google-internal migration only. Do not use.";
+        }
+
+        list uninterpreted_option {
+            key "identifier_value";
+            uses  UninterpretedOption;
+
+            description
+                "The parser stores options it doesn't recognize here. See above.";
+        }
+
+        typedef CType {
+            type enumeration {
+                enum STRING {
+                    description "";
+                }
+                enum CORD {
+                    description "";
+                }
+                enum STRING_PIECE {
+                    description "";
+                }
+            }
+            description
+                "";
+        }
+
+        typedef JSType {
+            type enumeration {
+                enum JS_NORMAL {
+                    description "";
+                }
+                enum JS_STRING {
+                    description "";
+                }
+                enum JS_NUMBER {
+                    description "";
+                }
+            }
+            description
+                "";
+        }
+
+    }
+
+    grouping OneofOptions {
+        description
+            "";
+        list uninterpreted_option {
+            key "identifier_value";
+            uses  UninterpretedOption;
+
+            description
+                "The parser stores options it doesn't recognize here. See above.";
+        }
+
+    }
+
+    grouping EnumOptions {
+        description
+            "";
+        leaf allow_alias {
+            type  boolean; 
+            description
+                "Set this option to true to allow mapping different tag names to the same
+ value.";
+        }
+
+        leaf deprecated {
+            type  boolean; 
+            description
+                "Is this enum deprecated?
+ Depending on the target platform, this can emit Deprecated annotations
+ for the enum, or it will be completely ignored; in the very least, this
+ is a formalization for deprecating enums.";
+        }
+
+        list uninterpreted_option {
+            key "identifier_value";
+            uses  UninterpretedOption;
+
+            description
+                "The parser stores options it doesn't recognize here. See above.";
+        }
+
+    }
+
+    grouping EnumValueOptions {
+        description
+            "";
+        leaf deprecated {
+            type  boolean; 
+            description
+                "Is this enum value deprecated?
+ Depending on the target platform, this can emit Deprecated annotations
+ for the enum value, or it will be completely ignored; in the very least,
+ this is a formalization for deprecating enum values.";
+        }
+
+        list uninterpreted_option {
+            key "identifier_value";
+            uses  UninterpretedOption;
+
+            description
+                "The parser stores options it doesn't recognize here. See above.";
+        }
+
+    }
+
+    grouping ServiceOptions {
+        description
+            "";
+        leaf deprecated {
+            type  boolean; 
+            description
+                "Is this service deprecated?
+ Depending on the target platform, this can emit Deprecated annotations
+ for the service, or it will be completely ignored; in the very least,
+ this is a formalization for deprecating services.
+Note:  Field numbers 1 through 32 are reserved for Google's internal RPC
+   framework.  We apologize for hoarding these numbers to ourselves, but
+   we were already using them long before we decided to release Protocol
+   Buffers.";
+        }
+
+        list uninterpreted_option {
+            key "identifier_value";
+            uses  UninterpretedOption;
+
+            description
+                "The parser stores options it doesn't recognize here. See above.";
+        }
+
+    }
+
+    grouping MethodOptions {
+        description
+            "";
+        leaf deprecated {
+            type  boolean; 
+            description
+                "Is this method deprecated?
+ Depending on the target platform, this can emit Deprecated annotations
+ for the method, or it will be completely ignored; in the very least,
+ this is a formalization for deprecating methods.
+Note:  Field numbers 1 through 32 are reserved for Google's internal RPC
+   framework.  We apologize for hoarding these numbers to ourselves, but
+   we were already using them long before we decided to release Protocol
+   Buffers.";
+        }
+
+        list uninterpreted_option {
+            key "identifier_value";
+            uses  UninterpretedOption;
+
+            description
+                "The parser stores options it doesn't recognize here. See above.";
+        }
+
+    }
+
+    grouping UninterpretedOption {
+        description
+            "A message representing a option the parser does not recognize. This only
+ appears in options protos created by the compiler::Parser class.
+ DescriptorPool resolves these when building Descriptor objects. Therefore,
+ options protos in descriptor objects (e.g. returned by Descriptor::options(),
+ or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
+ in them.";
+
+        leaf identifier_value {
+            type  string; 
+            description
+                "The value of the uninterpreted option, in whatever type the tokenizer
+ identified it as during parsing. Exactly one of these should be set.";
+        }
+
+        leaf positive_int_value {
+            type  uint64; 
+            description
+                "";
+        }
+
+        leaf negative_int_value {
+            type  int64; 
+            description
+                "";
+        }
+
+        leaf double_value {
+            type decimal64 {
+               fraction-digits 5;
+            }
+            description
+                "";
+        }
+
+        leaf string_value {
+            type  binary; 
+            description
+                "";
+        }
+
+        leaf aggregate_value {
+            type  string; 
+            description
+                "";
+        }
+
+        grouping NamePart {
+            description
+                "The name of the uninterpreted option.  Each string represents a segment in
+     a dot-separated name.  is_extension is true iff a segment represents an
+     extension (denoted with parentheses in options specs in .proto files).
+     E.g.,    foo , false ,   bar.baz , true ,   qux , false    represents
+      foo.(bar.baz).qux .";
+            leaf name_part {
+                type  string; 
+                description
+                    "";
+            }
+    
+            leaf is_extension {
+                type  boolean; 
+                description
+                    "";
+            }
+    
+        }
+    
+    }
+
+    grouping SourceCodeInfo {
+        description
+            "Encapsulates information about the original source file from which a
+ FileDescriptorProto was generated.
+===================================================================
+ Optional source code info";
+
+        grouping Location {
+            description
+                "";
+            list path {
+                key "path";
+                leaf path {
+                    type  int32; 
+                    description
+                        "Identifies which part of the FileDescriptorProto was defined at this
+     location.
+    
+     Each element is a field number or an index.  They form a path from
+     the root FileDescriptorProto to the place where the definition.  For
+     example, this path:
+         4, 3, 2, 7, 1  
+     refers to:
+       file.message_type(3)     4, 3
+           .field(7)            2, 7
+           .name()              1
+     This is because FileDescriptorProto.message_type has field number 4:
+       repeated DescriptorProto message_type = 4;
+     and DescriptorProto.field has field number 2:
+       repeated FieldDescriptorProto field = 2;
+     and FieldDescriptorProto.name has field number 1:
+       optional string name = 1;
+    
+     Thus, the above path gives the location of a field name.  If we removed
+     the last element:
+         4, 3, 2, 7  
+     this path refers to the whole field declaration (from the beginning
+     of the label to the terminating semicolon).";
+                }
+                description
+                    "Identifies which part of the FileDescriptorProto was defined at this
+     location.
+    
+     Each element is a field number or an index.  They form a path from
+     the root FileDescriptorProto to the place where the definition.  For
+     example, this path:
+         4, 3, 2, 7, 1  
+     refers to:
+       file.message_type(3)     4, 3
+           .field(7)            2, 7
+           .name()              1
+     This is because FileDescriptorProto.message_type has field number 4:
+       repeated DescriptorProto message_type = 4;
+     and DescriptorProto.field has field number 2:
+       repeated FieldDescriptorProto field = 2;
+     and FieldDescriptorProto.name has field number 1:
+       optional string name = 1;
+    
+     Thus, the above path gives the location of a field name.  If we removed
+     the last element:
+         4, 3, 2, 7  
+     this path refers to the whole field declaration (from the beginning
+     of the label to the terminating semicolon).";
+            }
+    
+            list span {
+                key "span";
+                leaf span {
+                    type  int32; 
+                    description
+                        "Always has exactly three or four elements: start line, start column,
+     end line (optional, otherwise assumed same as start line), end column.
+     These are packed into a single field for efficiency.  Note that line
+     and column numbers are zero-based -- typically you will want to add
+     1 to each before displaying to a user.";
+                }
+                description
+                    "Always has exactly three or four elements: start line, start column,
+     end line (optional, otherwise assumed same as start line), end column.
+     These are packed into a single field for efficiency.  Note that line
+     and column numbers are zero-based -- typically you will want to add
+     1 to each before displaying to a user.";
+            }
+    
+            leaf leading_comments {
+                type  string; 
+                description
+                    "If this SourceCodeInfo represents a complete declaration, these are any
+     comments appearing before and after the declaration which appear to be
+     attached to the declaration.
+    
+     A series of line comments appearing on consecutive lines, with no other
+     tokens appearing on those lines, will be treated as a single comment.
+    
+     leading_detached_comments will keep paragraphs of comments that appear
+     before (but not connected to) the current element. Each paragraph,
+     separated by empty lines, will be one comment element in the repeated
+     field.
+    
+     Only the comment content is provided; comment markers (e.g.   ) are
+     stripped out.  For block comments, leading whitespace and an asterisk
+     will be stripped from the beginning of each line other than the first.
+     Newlines are included in the output.
+    
+     Examples:
+    
+       optional int32 foo = 1;     Comment attached to foo.
+          Comment attached to bar.
+       optional int32 bar = 2;
+    
+       optional string baz = 3;
+          Comment attached to baz.
+          Another line attached to baz.
+    
+          Comment attached to qux.
+         
+          Another line attached to qux.
+       optional double qux = 4;
+    
+          Detached comment for corge. This is not leading or trailing comments
+          to qux or corge because there are blank lines separating it from
+          both.
+    
+          Detached comment for corge paragraph 2.
+    
+       optional string corge = 5;
+          Block comment attached
+          to corge.  Leading asterisks
+          will be removed.   
+          Block comment attached to
+          grault.   
+       optional int32 grault = 6;
+    
+          ignored detached comments.";
+            }
+    
+            leaf trailing_comments {
+                type  string; 
+                description
+                    "";
+            }
+    
+            list leading_detached_comments {
+                key "leading_detached_comments";
+                leaf leading_detached_comments {
+                    type  string; 
+                    description
+                        "";
+                }
+                description
+                    "";
+            }
+    
+        }
+    
+    }
+
+    container GeneratedCodeInfo {
+        description
+            "Describes the relationship between generated code and its original source
+ file. A GeneratedCodeInfo message is associated with only one generated
+ source file, but may contain references to different source .proto files.";
+
+        grouping Annotation {
+            description
+                "";
+            list path {
+                key "path";
+                leaf path {
+                    type  int32; 
+                    description
+                        "Identifies the element in the original source .proto file. This field
+     is formatted the same as SourceCodeInfo.Location.path.";
+                }
+                description
+                    "Identifies the element in the original source .proto file. This field
+     is formatted the same as SourceCodeInfo.Location.path.";
+            }
+    
+            leaf source_file {
+                type  string; 
+                description
+                    "Identifies the filesystem path to the original source .proto.";
+            }
+    
+            leaf begin {
+                type  int32; 
+                description
+                    "Identifies the starting offset in bytes in the generated code
+     that relates to the identified object.";
+            }
+    
+            leaf end {
+                type  int32; 
+                description
+                    "Identifies the ending offset in bytes in the generated code that
+     relates to the identified offset. The end offset should be one past
+     the last relevant byte (so the length of the text = end - begin).";
+            }
+    
+        }
+    
+    }
+
+}
\ No newline at end of file
diff --git a/experiments/netconf/proto2yang/ietf-device.yang b/experiments/netconf/proto2yang/ietf-device.yang
new file mode 100644
index 0000000..0a37cf3
--- /dev/null
+++ b/experiments/netconf/proto2yang/ietf-device.yang
@@ -0,0 +1,349 @@
+
+module ietf-device {
+
+
+    namespace "urn:opencord:params:xml:ns:voltha:ietf-device";
+    prefix device;
+
+    import ietf-openflow_13 { prefix openflow_13 ; }
+    import ietf-common { prefix common ; }
+    import ietf-any { prefix any ; }
+
+    organization "CORD";
+    contact
+        " Any name";
+
+    description
+        "";
+
+    revision "2016-11-15" {
+        description "Initial revision.";
+        reference "reference";
+    }
+
+
+    grouping DeviceType {
+        description
+            "A Device Type";
+        leaf id {
+            type  string; 
+            description
+                "Unique name for the device type";
+        }
+
+        leaf adapter {
+            type  string; 
+            description
+                "Name of the adapter that handles device type";
+        }
+
+        leaf accepts_bulk_flow_update {
+            type  boolean; 
+            description
+                "Capabilitities";
+        }
+
+        leaf accepts_add_remove_flow_updates {
+            type  boolean; 
+            description
+                "";
+        }
+
+    }
+
+    grouping DeviceTypes {
+        description
+            "A plurality of device types";
+        list items {
+            key "id";
+            uses  DeviceType;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping Port {
+        description
+            "";
+        leaf port_no {
+            type  uint32; 
+            description
+                "Device-unique port number";
+        }
+
+        leaf label {
+            type  string; 
+            description
+                "Arbitrary port label";
+        }
+
+        leaf type {
+            type  PortType; 
+            description
+                "Type of port";
+        }
+
+        leaf admin_state {
+            type  common:AdminState;
+
+            description
+                "";
+        }
+
+        leaf oper_status {
+            type  common:OperStatus;
+
+            description
+                "";
+        }
+
+        leaf device_id {
+            type  string; 
+            description
+                "Unique .id of device that owns this port";
+        }
+
+
+        typedef PortType {
+            type enumeration {
+                enum UNKNOWN {
+                    description "";
+                }
+                enum ETHERNET_NNI {
+                    description "";
+                }
+                enum ETHERNET_UNI {
+                    description "";
+                }
+                enum PON_OLT {
+                    description "";
+                }
+                enum PON_ONU {
+                    description "";
+                }
+            }
+            description
+                "";
+        }
+
+        grouping PeerPort {
+            description
+                "";
+            leaf device_id {
+                type  string; 
+                description
+                    "";
+            }
+    
+            leaf port_no {
+                type  uint32; 
+                description
+                    "";
+            }
+    
+        }
+    
+    }
+
+    grouping Ports {
+        description
+            "";
+        list items {
+            key "port_no";
+            uses  Port;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping Device {
+        description
+            "A Physical Device instance";
+        leaf id {
+            type  string; 
+            description
+                "Voltha's device identifier";
+        }
+
+        leaf type {
+            type  string; 
+            description
+                "Device type, refers to one of the registered device types";
+        }
+
+        leaf root {
+            type  boolean; 
+            description
+                "Is this device a root device. Each logical switch has one root
+ device that is associated with the logical flow switch.";
+        }
+
+        leaf parent_id {
+            type  string; 
+            description
+                "Parent device id, in the device tree (for a root device, the parent_id
+ is the logical_device.id)";
+        }
+
+        leaf parent_port_no {
+            type  uint32; 
+            description
+                "";
+        }
+
+        leaf vendor {
+            type  string; 
+            description
+                "Vendor, version, serial number, etc.";
+        }
+
+        leaf model {
+            type  string; 
+            description
+                "";
+        }
+
+        leaf hardware_version {
+            type  string; 
+            description
+                "";
+        }
+
+        leaf firmware_version {
+            type  string; 
+            description
+                "";
+        }
+
+        leaf software_version {
+            type  string; 
+            description
+                "";
+        }
+
+        leaf serial_number {
+            type  string; 
+            description
+                "";
+        }
+
+        leaf adapter {
+            type  string; 
+            description
+                "Addapter that takes care of device";
+        }
+
+        leaf vlan {
+            type  uint32; 
+            description
+                "Device contact on vlan (if 0, no vlan)";
+        }
+
+        leaf mac_address {
+            type  string; 
+            description
+                "Device contact MAC address (format:  xx:xx:xx:xx:xx:xx )";
+        }
+
+        leaf ipv4_address {
+            type  string; 
+            description
+                "Device contact IPv4 address (format:  a.b.c.d  or can use hostname too)";
+        }
+
+        leaf ipv6_address {
+            type  string; 
+            description
+                "Device contact IPv6 address using the canonical string form
+ ( xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx )";
+        }
+
+
+        leaf admin_state {
+            type  common:AdminState;
+
+            description
+                "";
+        }
+
+        leaf oper_status {
+            type  common:OperStatus;
+
+            description
+                "";
+        }
+
+        leaf connect_status {
+            type  common:ConnectStatus;
+
+            description
+                "";
+        }
+
+        container custom {
+            uses  any:Any;
+
+            description
+                "Device type specific attributes
+TODO additional common attribute here";
+        }
+
+        list ports {
+            key "port_no";
+            uses  Port;
+
+            description
+                "";
+        }
+
+        container flows {
+            uses  openflow_13:Flows;
+
+            description
+                "";
+        }
+
+        container flow_groups {
+            uses  openflow_13:FlowGroups;
+
+            description
+                "";
+        }
+
+        grouping ProxyAddress {
+            description
+                "";
+            leaf device_id {
+                type  string; 
+                description
+                    "Which device to use as proxy to this device";
+            }
+    
+            leaf channel_id {
+                type  uint32; 
+                description
+                    "Sub-address within proxy device";
+            }
+    
+        }
+    
+    }
+
+    grouping Devices {
+        description
+            "";
+        list items {
+            key "id";
+            uses  Device;
+
+            description
+                "";
+        }
+
+    }
+
+}
\ No newline at end of file
diff --git a/experiments/netconf/proto2yang/ietf-empty.yang b/experiments/netconf/proto2yang/ietf-empty.yang
new file mode 100644
index 0000000..c2ee52b
--- /dev/null
+++ b/experiments/netconf/proto2yang/ietf-empty.yang
@@ -0,0 +1,35 @@
+
+module ietf-empty {
+
+
+    namespace "urn:opencord:params:xml:ns:voltha:ietf-empty";
+    prefix empty;
+
+
+    organization "CORD";
+    contact
+        " Any name";
+
+    description
+        "";
+
+    revision "2016-11-15" {
+        description "Initial revision.";
+        reference "reference";
+    }
+
+
+    grouping Empty {
+        description
+            "A generic empty message that you can re-use to avoid defining duplicated
+ empty messages in your APIs. A typical example is to use it as the request
+ or the response type of an API method. For instance:
+
+     service Foo  
+       rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
+      
+
+ The JSON representation for `Empty` is empty JSON object `  `.";
+    }
+
+}
\ No newline at end of file
diff --git a/experiments/netconf/proto2yang/ietf-health.yang b/experiments/netconf/proto2yang/ietf-health.yang
new file mode 100644
index 0000000..e79c30a
--- /dev/null
+++ b/experiments/netconf/proto2yang/ietf-health.yang
@@ -0,0 +1,65 @@
+
+module ietf-health {
+
+
+    namespace "urn:opencord:params:xml:ns:voltha:ietf-health";
+    prefix health;
+
+    import ietf-empty { prefix empty ; }
+
+    organization "CORD";
+    contact
+        " Any name";
+
+    description
+        "";
+
+    revision "2016-11-15" {
+        description "Initial revision.";
+        reference "reference";
+    }
+
+
+    grouping HealthStatus {
+        description
+            "Encode health status of a Voltha instance";
+        leaf state {
+            type  HealthState; 
+            description
+                "Current state of health of this Voltha instance";
+        }
+
+        typedef HealthState {
+            type enumeration {
+                enum HEALTHY {
+                    description "";
+                }
+                enum OVERLOADED {
+                    description "";
+                }
+                enum DYING {
+                    description "";
+                }
+            }
+            description
+                "Health states";
+        }
+
+    }
+
+    /*  Health related services" */
+    rpc HealthService-GetHealthStatus {
+        description
+            "Return current health status of a Voltha instance";
+        input {
+            uses  empty:Empty;
+
+        }
+        output {
+            uses  HealthStatus;
+
+        }
+    }
+
+
+}
\ No newline at end of file
diff --git a/experiments/netconf/proto2yang/ietf-http.yang b/experiments/netconf/proto2yang/ietf-http.yang
new file mode 100644
index 0000000..3d9cf2c
--- /dev/null
+++ b/experiments/netconf/proto2yang/ietf-http.yang
@@ -0,0 +1,158 @@
+
+module ietf-http {
+
+
+    namespace "urn:opencord:params:xml:ns:voltha:ietf-http";
+    prefix http;
+
+
+    organization "CORD";
+    contact
+        " Any name";
+
+    description
+        "";
+
+    revision "2016-11-15" {
+        description "Initial revision.";
+        reference "reference";
+    }
+
+
+    grouping HttpRule {
+        description
+            "`HttpRule` defines the mapping of an RPC method to one or more HTTP REST API
+ methods. The mapping determines what portions of the request message are
+ populated from the path, query parameters, or body of the HTTP request.  The
+ mapping is typically specified as an `google.api.http` annotation, see
+  google api annotations.proto  for details.
+
+ The mapping consists of a mandatory field specifying a path template and an
+ optional `body` field specifying what data is represented in the HTTP request
+ body. The field name for the path indicates the HTTP method. Example:
+
+ ```
+ package google.storage.v2;
+
+ import  google api annotations.proto ;
+
+ service Storage  
+   rpc CreateObject(CreateObjectRequest) returns (Object)  
+     option (google.api.http)  
+       post:   v2  bucket_name=buckets    objects 
+       body:  object 
+      ;
+    ;
+  
+ ```
+
+ Here `bucket_name` and `object` bind to fields of the request message
+ `CreateObjectRequest`.
+
+ The rules for mapping HTTP path, query parameters, and body fields
+ to the request message are as follows:
+
+ 1. The `body` field specifies either ` ` or a field path, or is
+    omitted. If omitted, it assumes there is no HTTP body.
+ 2. Leaf fields (recursive expansion of nested messages in the
+    request) can be classified into three types:
+     (a) Matched in the URL template.
+     (b) Covered by body (if body is ` `, everything except (a) fields;
+         else everything under the body field)
+     (c) All other fields.
+ 3. URL query parameters found in the HTTP request are mapped to (c) fields.
+ 4. Any body sent with an HTTP request can contain only (b) fields.
+
+ The syntax of the path template is as follows:
+
+     Template =     Segments   Verb   ;
+     Segments = Segment       Segment   ;
+     Segment  =     |      | LITERAL | Variable ;
+     Variable =     FieldPath    =  Segments       ;
+     FieldPath = IDENT    .  IDENT   ;
+     Verb     =  :  LITERAL ;
+
+ ` ` matches a single path component, `  ` zero or more path components, and
+ `LITERAL` a constant.  A `Variable` can match an entire path as specified
+ again by a template; this nested template must not contain further variables.
+ If no template is given with a variable, it matches a single path component.
+ The notation ` var ` is henceforth equivalent to ` var=  `.
+
+ Use CustomHttpPattern to specify any HTTP method that is not included in the
+ pattern field, such as HEAD, or     to leave the HTTP method unspecified for
+ a given URL path rule. The wild-card rule is useful for services that provide
+ content to Web (HTML) clients.";
+        leaf get {
+            type  string; 
+            description
+                "Used for listing and getting information about resources.";
+        }
+
+        leaf put {
+            type  string; 
+            description
+                "Used for updating a resource.";
+        }
+
+        leaf post {
+            type  string; 
+            description
+                "Used for creating a resource.";
+        }
+
+        leaf delete {
+            type  string; 
+            description
+                "Used for deleting a resource.";
+        }
+
+        leaf patch {
+            type  string; 
+            description
+                "Used for updating a resource.";
+        }
+
+        container custom {
+            uses  CustomHttpPattern;
+
+            description
+                "Custom pattern is used for defining custom verbs.";
+        }
+
+        leaf body {
+            type  string; 
+            description
+                "The name of the request field whose value is mapped to the HTTP body, or
+ ` ` for mapping all fields not captured by the path pattern to the HTTP
+ body.";
+        }
+
+        list additional_bindings {
+            key "get";
+            uses  HttpRule;
+
+            description
+                "Additional HTTP bindings for the selector. Nested bindings must not
+ specify a selector and must not contain additional bindings.";
+        }
+
+    }
+
+    grouping CustomHttpPattern {
+        description
+            "A custom pattern is used for defining custom HTTP verb.";
+        leaf kind {
+            type  string; 
+            description
+                "The name of this custom HTTP verb.";
+        }
+
+        leaf path {
+            type  string; 
+            description
+                "The path matched by this custom verb.";
+        }
+
+    }
+
+}
\ No newline at end of file
diff --git a/experiments/netconf/proto2yang/ietf-logical_device.yang b/experiments/netconf/proto2yang/ietf-logical_device.yang
new file mode 100644
index 0000000..6c65d4d
--- /dev/null
+++ b/experiments/netconf/proto2yang/ietf-logical_device.yang
@@ -0,0 +1,144 @@
+
+module ietf-logical_device {
+
+
+    namespace "urn:opencord:params:xml:ns:voltha:ietf-logical_device";
+    prefix logical_device;
+
+    import ietf-openflow_13 { prefix openflow_13 ; }
+
+    organization "CORD";
+    contact
+        " Any name";
+
+    description
+        "";
+
+    revision "2016-11-15" {
+        description "Initial revision.";
+        reference "reference";
+    }
+
+
+    grouping LogicalPort {
+        description
+            "";
+        leaf id {
+            type  string; 
+            description
+                "";
+        }
+
+        container ofp_port {
+            uses  openflow_13:ofp_port;
+
+            description
+                "";
+        }
+
+        leaf device_id {
+            type  string; 
+            description
+                "";
+        }
+
+        leaf device_port_no {
+            type  uint32; 
+            description
+                "";
+        }
+
+        leaf root_port {
+            type  boolean; 
+            description
+                "";
+        }
+
+    }
+
+    grouping LogicalPorts {
+        description
+            "";
+        list items {
+            key "id";
+            uses  LogicalPort;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping LogicalDevice {
+        description
+            "";
+        leaf id {
+            type  string; 
+            description
+                "unique id of logical device";
+        }
+
+        leaf datapath_id {
+            type  uint64; 
+            description
+                "unique datapath id for the logical device (used by the SDN controller)";
+        }
+
+        container desc {
+            uses  openflow_13:ofp_desc;
+
+            description
+                "device description";
+        }
+
+        container switch_features {
+            uses  openflow_13:ofp_switch_features;
+
+            description
+                "device features";
+        }
+
+        leaf root_device_id {
+            type  string; 
+            description
+                "name of the root device anchoring logical device";
+        }
+
+        list ports {
+            key "id";
+            uses  LogicalPort;
+
+            description
+                "logical device ports";
+        }
+
+        container flows {
+            uses  openflow_13:Flows;
+
+            description
+                "flows configured on the logical device";
+        }
+
+        container flow_groups {
+            uses  openflow_13:FlowGroups;
+
+            description
+                "flow groups configured on the logical device";
+        }
+
+    }
+
+    grouping LogicalDevices {
+        description
+            "";
+        list items {
+            key "id";
+            uses  LogicalDevice;
+
+            description
+                "";
+        }
+
+    }
+
+}
\ No newline at end of file
diff --git a/experiments/netconf/proto2yang/ietf-meta.yang b/experiments/netconf/proto2yang/ietf-meta.yang
new file mode 100644
index 0000000..92a480a
--- /dev/null
+++ b/experiments/netconf/proto2yang/ietf-meta.yang
@@ -0,0 +1,45 @@
+
+module ietf-meta {
+
+
+    namespace "urn:opencord:params:xml:ns:voltha:ietf-meta";
+    prefix meta;
+
+
+    organization "CORD";
+    contact
+        " Any name";
+
+    description
+        "";
+
+    revision "2016-11-15" {
+        description "Initial revision.";
+        reference "reference";
+    }
+
+    typedef Access {
+        type enumeration {
+            enum CONFIG {
+                description "";
+            }
+            enum READ_ONLY {
+                description "";
+            }
+        }
+        description
+            "";
+    }
+
+    container ChildNode {
+        description
+            "";
+        leaf key {
+            type  string; 
+            description
+                "";
+        }
+
+    }
+
+}
\ No newline at end of file
diff --git a/experiments/netconf/proto2yang/ietf-openflow_13.yang b/experiments/netconf/proto2yang/ietf-openflow_13.yang
new file mode 100644
index 0000000..43b0bcb
--- /dev/null
+++ b/experiments/netconf/proto2yang/ietf-openflow_13.yang
@@ -0,0 +1,4873 @@
+
+module ietf-openflow_13 {
+
+
+    namespace "urn:opencord:params:xml:ns:voltha:ietf-openflow_13";
+    prefix openflow_13;
+
+
+    organization "CORD";
+    contact
+        " Any name";
+
+    description
+        "";
+
+    revision "2016-11-15" {
+        description "Initial revision.";
+        reference "reference";
+    }
+
+    typedef ofp_port_no {
+        type enumeration {
+            enum OFPP_INVALID {
+                description "";
+            }
+            enum OFPP_MAX {
+                description "";
+            }
+            enum OFPP_IN_PORT {
+                description "";
+            }
+            enum OFPP_TABLE {
+                description "";
+            }
+            enum OFPP_NORMAL {
+                description "";
+            }
+            enum OFPP_FLOOD {
+                description "";
+            }
+            enum OFPP_ALL {
+                description "";
+            }
+            enum OFPP_CONTROLLER {
+                description "";
+            }
+            enum OFPP_LOCAL {
+                description "";
+            }
+            enum OFPP_ANY {
+                description "";
+            }
+        }
+        description
+            "Port numbering. Ports are numbered starting from 1.Version number:
+ OpenFlow versions released: 0x01 = 1.0 ; 0x02 = 1.1 ; 0x03 = 1.2
+     0x04 = 1.3
+The most significant bit in the version field is reserved and must
+ be set to zero.
+#define OFP_VERSION   0x04
+#define PIPELINE_TABLES 64
+#define OFP_MAX_TABLE_NAME_LEN 32
+#define OFP_MAX_PORT_NAME_LEN  16
+Official IANA registered port for OpenFlow.#define OFP_TCP_PORT  6653
+#define OFP_SSL_PORT  6653
+#define OFP_ETH_ALEN 6             Bytes in an Ethernet address.   ";
+    }
+    typedef ofp_type {
+        type enumeration {
+            enum OFPT_HELLO {
+                description "";
+            }
+            enum OFPT_ERROR {
+                description "";
+            }
+            enum OFPT_ECHO_REQUEST {
+                description "";
+            }
+            enum OFPT_ECHO_REPLY {
+                description "";
+            }
+            enum OFPT_EXPERIMENTER {
+                description "";
+            }
+            enum OFPT_FEATURES_REQUEST {
+                description "";
+            }
+            enum OFPT_FEATURES_REPLY {
+                description "";
+            }
+            enum OFPT_GET_CONFIG_REQUEST {
+                description "";
+            }
+            enum OFPT_GET_CONFIG_REPLY {
+                description "";
+            }
+            enum OFPT_SET_CONFIG {
+                description "";
+            }
+            enum OFPT_PACKET_IN {
+                description "";
+            }
+            enum OFPT_FLOW_REMOVED {
+                description "";
+            }
+            enum OFPT_PORT_STATUS {
+                description "";
+            }
+            enum OFPT_PACKET_OUT {
+                description "";
+            }
+            enum OFPT_FLOW_MOD {
+                description "";
+            }
+            enum OFPT_GROUP_MOD {
+                description "";
+            }
+            enum OFPT_PORT_MOD {
+                description "";
+            }
+            enum OFPT_TABLE_MOD {
+                description "";
+            }
+            enum OFPT_MULTIPART_REQUEST {
+                description "";
+            }
+            enum OFPT_MULTIPART_REPLY {
+                description "";
+            }
+            enum OFPT_BARRIER_REQUEST {
+                description "";
+            }
+            enum OFPT_BARRIER_REPLY {
+                description "";
+            }
+            enum OFPT_QUEUE_GET_CONFIG_REQUEST {
+                description "";
+            }
+            enum OFPT_QUEUE_GET_CONFIG_REPLY {
+                description "";
+            }
+            enum OFPT_ROLE_REQUEST {
+                description "";
+            }
+            enum OFPT_ROLE_REPLY {
+                description "";
+            }
+            enum OFPT_GET_ASYNC_REQUEST {
+                description "";
+            }
+            enum OFPT_GET_ASYNC_REPLY {
+                description "";
+            }
+            enum OFPT_SET_ASYNC {
+                description "";
+            }
+            enum OFPT_METER_MOD {
+                description "";
+            }
+        }
+        description
+            "";
+    }
+    typedef ofp_hello_elem_type {
+        type enumeration {
+            enum OFPHET_INVALID {
+                description "";
+            }
+            enum OFPHET_VERSIONBITMAP {
+                description "";
+            }
+        }
+        description
+            "Hello elements types.";
+    }
+    typedef ofp_config_flags {
+        type enumeration {
+            enum OFPC_FRAG_NORMAL {
+                description "";
+            }
+            enum OFPC_FRAG_DROP {
+                description "";
+            }
+            enum OFPC_FRAG_REASM {
+                description "";
+            }
+            enum OFPC_FRAG_MASK {
+                description "";
+            }
+        }
+        description
+            "#define OFP_DEFAULT_MISS_SEND_LEN   128";
+    }
+    typedef ofp_table_config {
+        type enumeration {
+            enum OFPTC_INVALID {
+                description "";
+            }
+            enum OFPTC_DEPRECATED_MASK {
+                description "";
+            }
+        }
+        description
+            "Flags to configure the table. Reserved for future use.";
+    }
+    typedef ofp_table {
+        type enumeration {
+            enum OFPTT_INVALID {
+                description "";
+            }
+            enum OFPTT_MAX {
+                description "";
+            }
+            enum OFPTT_ALL {
+                description "";
+            }
+        }
+        description
+            "Table numbering. Tables can use any number up to OFPT_MAX.";
+    }
+    typedef ofp_capabilities {
+        type enumeration {
+            enum OFPC_INVALID {
+                description "";
+            }
+            enum OFPC_FLOW_STATS {
+                description "";
+            }
+            enum OFPC_TABLE_STATS {
+                description "";
+            }
+            enum OFPC_PORT_STATS {
+                description "";
+            }
+            enum OFPC_GROUP_STATS {
+                description "";
+            }
+            enum OFPC_IP_REASM {
+                description "";
+            }
+            enum OFPC_QUEUE_STATS {
+                description "";
+            }
+            enum OFPC_PORT_BLOCKED {
+                description "";
+            }
+        }
+        description
+            "Capabilities supported by the datapath.";
+    }
+    typedef ofp_port_config {
+        type enumeration {
+            enum OFPPC_INVALID {
+                description "";
+            }
+            enum OFPPC_PORT_DOWN {
+                description "";
+            }
+            enum OFPPC_NO_RECV {
+                description "";
+            }
+            enum OFPPC_NO_FWD {
+                description "";
+            }
+            enum OFPPC_NO_PACKET_IN {
+                description "";
+            }
+        }
+        description
+            "Flags to indicate behavior of the physical port.  These flags are
+ used in ofp_port to describe the current configuration.  They are
+ used in the ofp_port_mod message to configure the port's behavior.";
+    }
+    typedef ofp_port_state {
+        type enumeration {
+            enum OFPPS_INVALID {
+                description "";
+            }
+            enum OFPPS_LINK_DOWN {
+                description "";
+            }
+            enum OFPPS_BLOCKED {
+                description "";
+            }
+            enum OFPPS_LIVE {
+                description "";
+            }
+        }
+        description
+            "Current state of the physical port.  These are not configurable from
+ the controller.";
+    }
+    typedef ofp_port_features {
+        type enumeration {
+            enum OFPPF_INVALID {
+                description "";
+            }
+            enum OFPPF_10MB_HD {
+                description "";
+            }
+            enum OFPPF_10MB_FD {
+                description "";
+            }
+            enum OFPPF_100MB_HD {
+                description "";
+            }
+            enum OFPPF_100MB_FD {
+                description "";
+            }
+            enum OFPPF_1GB_HD {
+                description "";
+            }
+            enum OFPPF_1GB_FD {
+                description "";
+            }
+            enum OFPPF_10GB_FD {
+                description "";
+            }
+            enum OFPPF_40GB_FD {
+                description "";
+            }
+            enum OFPPF_100GB_FD {
+                description "";
+            }
+            enum OFPPF_1TB_FD {
+                description "";
+            }
+            enum OFPPF_OTHER {
+                description "";
+            }
+            enum OFPPF_COPPER {
+                description "";
+            }
+            enum OFPPF_FIBER {
+                description "";
+            }
+            enum OFPPF_AUTONEG {
+                description "";
+            }
+            enum OFPPF_PAUSE {
+                description "";
+            }
+            enum OFPPF_PAUSE_ASYM {
+                description "";
+            }
+        }
+        description
+            "Features of ports available in a datapath.";
+    }
+    typedef ofp_port_reason {
+        type enumeration {
+            enum OFPPR_ADD {
+                description "";
+            }
+            enum OFPPR_DELETE {
+                description "";
+            }
+            enum OFPPR_MODIFY {
+                description "";
+            }
+        }
+        description
+            "What changed about the physical port";
+    }
+    typedef ofp_match_type {
+        type enumeration {
+            enum OFPMT_STANDARD {
+                description "";
+            }
+            enum OFPMT_OXM {
+                description "";
+            }
+        }
+        description
+            "The match type indicates the match structure (set of fields that compose the
+ match) in use. The match type is placed in the type field at the beginning
+ of all match structures. The  OpenFlow Extensible Match  type corresponds
+ to OXM TLV format described below and must be supported by all OpenFlow
+ switches. Extensions that define other match types may be published on the
+ ONF wiki. Support for extensions is optional.
+## -------------------------- #### OpenFlow Extensible Match. #### -------------------------- ##";
+    }
+    typedef ofp_oxm_class {
+        type enumeration {
+            enum OFPXMC_NXM_0 {
+                description "";
+            }
+            enum OFPXMC_NXM_1 {
+                description "";
+            }
+            enum OFPXMC_OPENFLOW_BASIC {
+                description "";
+            }
+            enum OFPXMC_EXPERIMENTER {
+                description "";
+            }
+        }
+        description
+            "OXM Class IDs.
+ The high order bit differentiate reserved classes from member classes.
+ Classes 0x0000 to 0x7FFF are member classes, allocated by ONF.
+ Classes 0x8000 to 0xFFFE are reserved classes, reserved for standardisation.
+Components of a OXM TLV header.
+ Those macros are not valid for the experimenter class, macros for the
+ experimenter class will depend on the experimenter header used.#define OXM_HEADER__(CLASS, FIELD, HASMASK, LENGTH)  
+    (((CLASS) << 16) | ((FIELD) << 9) | ((HASMASK) << 8) | (LENGTH))
+#define OXM_HEADER(CLASS, FIELD, LENGTH)  
+    OXM_HEADER__(CLASS, FIELD, 0, LENGTH)
+#define OXM_HEADER_W(CLASS, FIELD, LENGTH)  
+    OXM_HEADER__(CLASS, FIELD, 1, (LENGTH)   2)
+#define OXM_CLASS(HEADER) ((HEADER) >> 16)
+#define OXM_FIELD(HEADER) (((HEADER) >> 9) & 0x7f)
+#define OXM_TYPE(HEADER) (((HEADER) >> 9) & 0x7fffff)
+#define OXM_HASMASK(HEADER) (((HEADER) >> 8) & 1)
+#define OXM_LENGTH(HEADER) ((HEADER) & 0xff)
+
+#define OXM_MAKE_WILD_HEADER(HEADER)  
+    OXM_HEADER_W(OXM_CLASS(HEADER), OXM_FIELD(HEADER), OXM_LENGTH(HEADER))";
+    }
+    typedef oxm_ofb_field_types {
+        type enumeration {
+            enum OFPXMT_OFB_IN_PORT {
+                description "";
+            }
+            enum OFPXMT_OFB_IN_PHY_PORT {
+                description "";
+            }
+            enum OFPXMT_OFB_METADATA {
+                description "";
+            }
+            enum OFPXMT_OFB_ETH_DST {
+                description "";
+            }
+            enum OFPXMT_OFB_ETH_SRC {
+                description "";
+            }
+            enum OFPXMT_OFB_ETH_TYPE {
+                description "";
+            }
+            enum OFPXMT_OFB_VLAN_VID {
+                description "";
+            }
+            enum OFPXMT_OFB_VLAN_PCP {
+                description "";
+            }
+            enum OFPXMT_OFB_IP_DSCP {
+                description "";
+            }
+            enum OFPXMT_OFB_IP_ECN {
+                description "";
+            }
+            enum OFPXMT_OFB_IP_PROTO {
+                description "";
+            }
+            enum OFPXMT_OFB_IPV4_SRC {
+                description "";
+            }
+            enum OFPXMT_OFB_IPV4_DST {
+                description "";
+            }
+            enum OFPXMT_OFB_TCP_SRC {
+                description "";
+            }
+            enum OFPXMT_OFB_TCP_DST {
+                description "";
+            }
+            enum OFPXMT_OFB_UDP_SRC {
+                description "";
+            }
+            enum OFPXMT_OFB_UDP_DST {
+                description "";
+            }
+            enum OFPXMT_OFB_SCTP_SRC {
+                description "";
+            }
+            enum OFPXMT_OFB_SCTP_DST {
+                description "";
+            }
+            enum OFPXMT_OFB_ICMPV4_TYPE {
+                description "";
+            }
+            enum OFPXMT_OFB_ICMPV4_CODE {
+                description "";
+            }
+            enum OFPXMT_OFB_ARP_OP {
+                description "";
+            }
+            enum OFPXMT_OFB_ARP_SPA {
+                description "";
+            }
+            enum OFPXMT_OFB_ARP_TPA {
+                description "";
+            }
+            enum OFPXMT_OFB_ARP_SHA {
+                description "";
+            }
+            enum OFPXMT_OFB_ARP_THA {
+                description "";
+            }
+            enum OFPXMT_OFB_IPV6_SRC {
+                description "";
+            }
+            enum OFPXMT_OFB_IPV6_DST {
+                description "";
+            }
+            enum OFPXMT_OFB_IPV6_FLABEL {
+                description "";
+            }
+            enum OFPXMT_OFB_ICMPV6_TYPE {
+                description "";
+            }
+            enum OFPXMT_OFB_ICMPV6_CODE {
+                description "";
+            }
+            enum OFPXMT_OFB_IPV6_ND_TARGET {
+                description "";
+            }
+            enum OFPXMT_OFB_IPV6_ND_SLL {
+                description "";
+            }
+            enum OFPXMT_OFB_IPV6_ND_TLL {
+                description "";
+            }
+            enum OFPXMT_OFB_MPLS_LABEL {
+                description "";
+            }
+            enum OFPXMT_OFB_MPLS_TC {
+                description "";
+            }
+            enum OFPXMT_OFB_MPLS_BOS {
+                description "";
+            }
+            enum OFPXMT_OFB_PBB_ISID {
+                description "";
+            }
+            enum OFPXMT_OFB_TUNNEL_ID {
+                description "";
+            }
+            enum OFPXMT_OFB_IPV6_EXTHDR {
+                description "";
+            }
+        }
+        description
+            "OXM Flow field types for OpenFlow basic class.";
+    }
+    typedef ofp_vlan_id {
+        type enumeration {
+            enum OFPVID_NONE {
+                description "";
+            }
+            enum OFPVID_PRESENT {
+                description "";
+            }
+        }
+        description
+            "The VLAN id is 12-bits, so we can use the entire 16 bits to indicate
+ special conditions.";
+    }
+    typedef ofp_ipv6exthdr_flags {
+        type enumeration {
+            enum OFPIEH_INVALID {
+                description "";
+            }
+            enum OFPIEH_NONEXT {
+                description "";
+            }
+            enum OFPIEH_ESP {
+                description "";
+            }
+            enum OFPIEH_AUTH {
+                description "";
+            }
+            enum OFPIEH_DEST {
+                description "";
+            }
+            enum OFPIEH_FRAG {
+                description "";
+            }
+            enum OFPIEH_ROUTER {
+                description "";
+            }
+            enum OFPIEH_HOP {
+                description "";
+            }
+            enum OFPIEH_UNREP {
+                description "";
+            }
+            enum OFPIEH_UNSEQ {
+                description "";
+            }
+        }
+        description
+            "Bit definitions for IPv6 Extension Header pseudo-field.#define OFP_VLAN_NONE      OFPVID_NONE";
+    }
+    typedef ofp_action_type {
+        type enumeration {
+            enum OFPAT_OUTPUT {
+                description "";
+            }
+            enum OFPAT_COPY_TTL_OUT {
+                description "";
+            }
+            enum OFPAT_COPY_TTL_IN {
+                description "";
+            }
+            enum OFPAT_SET_MPLS_TTL {
+                description "";
+            }
+            enum OFPAT_DEC_MPLS_TTL {
+                description "";
+            }
+            enum OFPAT_PUSH_VLAN {
+                description "";
+            }
+            enum OFPAT_POP_VLAN {
+                description "";
+            }
+            enum OFPAT_PUSH_MPLS {
+                description "";
+            }
+            enum OFPAT_POP_MPLS {
+                description "";
+            }
+            enum OFPAT_SET_QUEUE {
+                description "";
+            }
+            enum OFPAT_GROUP {
+                description "";
+            }
+            enum OFPAT_SET_NW_TTL {
+                description "";
+            }
+            enum OFPAT_DEC_NW_TTL {
+                description "";
+            }
+            enum OFPAT_SET_FIELD {
+                description "";
+            }
+            enum OFPAT_PUSH_PBB {
+                description "";
+            }
+            enum OFPAT_POP_PBB {
+                description "";
+            }
+            enum OFPAT_EXPERIMENTER {
+                description "";
+            }
+        }
+        description
+            "## ----------------- #### OpenFlow Actions. #### ----------------- ##";
+    }
+    typedef ofp_controller_max_len {
+        type enumeration {
+            enum OFPCML_INVALID {
+                description "";
+            }
+            enum OFPCML_MAX {
+                description "";
+            }
+            enum OFPCML_NO_BUFFER {
+                description "";
+            }
+        }
+        description
+            "";
+    }
+    typedef ofp_instruction_type {
+        type enumeration {
+            enum OFPIT_INVALID {
+                description "";
+            }
+            enum OFPIT_GOTO_TABLE {
+                description "";
+            }
+            enum OFPIT_WRITE_METADATA {
+                description "";
+            }
+            enum OFPIT_WRITE_ACTIONS {
+                description "";
+            }
+            enum OFPIT_APPLY_ACTIONS {
+                description "";
+            }
+            enum OFPIT_CLEAR_ACTIONS {
+                description "";
+            }
+            enum OFPIT_METER {
+                description "";
+            }
+            enum OFPIT_EXPERIMENTER {
+                description "";
+            }
+        }
+        description
+            "## ---------------------- #### OpenFlow Instructions. #### ---------------------- ##";
+    }
+    typedef ofp_flow_mod_command {
+        type enumeration {
+            enum OFPFC_ADD {
+                description "";
+            }
+            enum OFPFC_MODIFY {
+                description "";
+            }
+            enum OFPFC_MODIFY_STRICT {
+                description "";
+            }
+            enum OFPFC_DELETE {
+                description "";
+            }
+            enum OFPFC_DELETE_STRICT {
+                description "";
+            }
+        }
+        description
+            "## --------------------------- #### OpenFlow Flow Modification. #### --------------------------- ##";
+    }
+    typedef ofp_flow_mod_flags {
+        type enumeration {
+            enum OFPFF_INVALID {
+                description "";
+            }
+            enum OFPFF_SEND_FLOW_REM {
+                description "";
+            }
+            enum OFPFF_CHECK_OVERLAP {
+                description "";
+            }
+            enum OFPFF_RESET_COUNTS {
+                description "";
+            }
+            enum OFPFF_NO_PKT_COUNTS {
+                description "";
+            }
+            enum OFPFF_NO_BYT_COUNTS {
+                description "";
+            }
+        }
+        description
+            "Value used in  idle_timeout  and  hard_timeout  to indicate that the entry
+ is permanent.#define OFP_FLOW_PERMANENT 0
+By default, choose a priority in the middle.#define OFP_DEFAULT_PRIORITY 0x8000";
+    }
+    typedef ofp_group {
+        type enumeration {
+            enum OFPG_INVALID {
+                description "";
+            }
+            enum OFPG_MAX {
+                description "";
+            }
+            enum OFPG_ALL {
+                description "";
+            }
+            enum OFPG_ANY {
+                description "";
+            }
+        }
+        description
+            "Group numbering. Groups can use any number up to OFPG_MAX.";
+    }
+    typedef ofp_group_mod_command {
+        type enumeration {
+            enum OFPGC_ADD {
+                description "";
+            }
+            enum OFPGC_MODIFY {
+                description "";
+            }
+            enum OFPGC_DELETE {
+                description "";
+            }
+        }
+        description
+            "Group commands";
+    }
+    typedef ofp_group_type {
+        type enumeration {
+            enum OFPGT_ALL {
+                description "";
+            }
+            enum OFPGT_SELECT {
+                description "";
+            }
+            enum OFPGT_INDIRECT {
+                description "";
+            }
+            enum OFPGT_FF {
+                description "";
+            }
+        }
+        description
+            "Group types.  Values in the range  128; 255  are reserved for experimental
+ use.";
+    }
+    typedef ofp_packet_in_reason {
+        type enumeration {
+            enum OFPR_NO_MATCH {
+                description "";
+            }
+            enum OFPR_ACTION {
+                description "";
+            }
+            enum OFPR_INVALID_TTL {
+                description "";
+            }
+        }
+        description
+            "Why is this packet being sent to the controller?";
+    }
+    typedef ofp_flow_removed_reason {
+        type enumeration {
+            enum OFPRR_IDLE_TIMEOUT {
+                description "";
+            }
+            enum OFPRR_HARD_TIMEOUT {
+                description "";
+            }
+            enum OFPRR_DELETE {
+                description "";
+            }
+            enum OFPRR_GROUP_DELETE {
+                description "";
+            }
+            enum OFPRR_METER_DELETE {
+                description "";
+            }
+        }
+        description
+            "Why was this flow removed?";
+    }
+    typedef ofp_meter {
+        type enumeration {
+            enum OFPM_ZERO {
+                description "";
+            }
+            enum OFPM_MAX {
+                description "";
+            }
+            enum OFPM_SLOWPATH {
+                description "";
+            }
+            enum OFPM_CONTROLLER {
+                description "";
+            }
+            enum OFPM_ALL {
+                description "";
+            }
+        }
+        description
+            "Meter numbering. Flow meters can use any number up to OFPM_MAX.";
+    }
+    typedef ofp_meter_band_type {
+        type enumeration {
+            enum OFPMBT_INVALID {
+                description "";
+            }
+            enum OFPMBT_DROP {
+                description "";
+            }
+            enum OFPMBT_DSCP_REMARK {
+                description "";
+            }
+            enum OFPMBT_EXPERIMENTER {
+                description "";
+            }
+        }
+        description
+            "Meter band types";
+    }
+    typedef ofp_meter_mod_command {
+        type enumeration {
+            enum OFPMC_ADD {
+                description "";
+            }
+            enum OFPMC_MODIFY {
+                description "";
+            }
+            enum OFPMC_DELETE {
+                description "";
+            }
+        }
+        description
+            "Meter commands";
+    }
+    typedef ofp_meter_flags {
+        type enumeration {
+            enum OFPMF_INVALID {
+                description "";
+            }
+            enum OFPMF_KBPS {
+                description "";
+            }
+            enum OFPMF_PKTPS {
+                description "";
+            }
+            enum OFPMF_BURST {
+                description "";
+            }
+            enum OFPMF_STATS {
+                description "";
+            }
+        }
+        description
+            "Meter configuration flags";
+    }
+    typedef ofp_error_type {
+        type enumeration {
+            enum OFPET_HELLO_FAILED {
+                description "";
+            }
+            enum OFPET_BAD_REQUEST {
+                description "";
+            }
+            enum OFPET_BAD_ACTION {
+                description "";
+            }
+            enum OFPET_BAD_INSTRUCTION {
+                description "";
+            }
+            enum OFPET_BAD_MATCH {
+                description "";
+            }
+            enum OFPET_FLOW_MOD_FAILED {
+                description "";
+            }
+            enum OFPET_GROUP_MOD_FAILED {
+                description "";
+            }
+            enum OFPET_PORT_MOD_FAILED {
+                description "";
+            }
+            enum OFPET_TABLE_MOD_FAILED {
+                description "";
+            }
+            enum OFPET_QUEUE_OP_FAILED {
+                description "";
+            }
+            enum OFPET_SWITCH_CONFIG_FAILED {
+                description "";
+            }
+            enum OFPET_ROLE_REQUEST_FAILED {
+                description "";
+            }
+            enum OFPET_METER_MOD_FAILED {
+                description "";
+            }
+            enum OFPET_TABLE_FEATURES_FAILED {
+                description "";
+            }
+            enum OFPET_EXPERIMENTER {
+                description "";
+            }
+        }
+        description
+            "Values for 'type' in ofp_error_message.  These values are immutable: they
+ will not change in future versions of the protocol (although new values may
+ be added).";
+    }
+    typedef ofp_hello_failed_code {
+        type enumeration {
+            enum OFPHFC_INCOMPATIBLE {
+                description "";
+            }
+            enum OFPHFC_EPERM {
+                description "";
+            }
+        }
+        description
+            "ofp_error_msg 'code' values for OFPET_HELLO_FAILED.  'data' contains an
+ ASCII text string that may give failure details.";
+    }
+    typedef ofp_bad_request_code {
+        type enumeration {
+            enum OFPBRC_BAD_VERSION {
+                description "";
+            }
+            enum OFPBRC_BAD_TYPE {
+                description "";
+            }
+            enum OFPBRC_BAD_MULTIPART {
+                description "";
+            }
+            enum OFPBRC_BAD_EXPERIMENTER {
+                description "";
+            }
+            enum OFPBRC_BAD_EXP_TYPE {
+                description "";
+            }
+            enum OFPBRC_EPERM {
+                description "";
+            }
+            enum OFPBRC_BAD_LEN {
+                description "";
+            }
+            enum OFPBRC_BUFFER_EMPTY {
+                description "";
+            }
+            enum OFPBRC_BUFFER_UNKNOWN {
+                description "";
+            }
+            enum OFPBRC_BAD_TABLE_ID {
+                description "";
+            }
+            enum OFPBRC_IS_SLAVE {
+                description "";
+            }
+            enum OFPBRC_BAD_PORT {
+                description "";
+            }
+            enum OFPBRC_BAD_PACKET {
+                description "";
+            }
+            enum OFPBRC_MULTIPART_BUFFER_OVERFLOW {
+                description "";
+            }
+        }
+        description
+            "ofp_error_msg 'code' values for OFPET_BAD_REQUEST.  'data' contains at least
+ the first 64 bytes of the failed request.";
+    }
+    typedef ofp_bad_action_code {
+        type enumeration {
+            enum OFPBAC_BAD_TYPE {
+                description "";
+            }
+            enum OFPBAC_BAD_LEN {
+                description "";
+            }
+            enum OFPBAC_BAD_EXPERIMENTER {
+                description "";
+            }
+            enum OFPBAC_BAD_EXP_TYPE {
+                description "";
+            }
+            enum OFPBAC_BAD_OUT_PORT {
+                description "";
+            }
+            enum OFPBAC_BAD_ARGUMENT {
+                description "";
+            }
+            enum OFPBAC_EPERM {
+                description "";
+            }
+            enum OFPBAC_TOO_MANY {
+                description "";
+            }
+            enum OFPBAC_BAD_QUEUE {
+                description "";
+            }
+            enum OFPBAC_BAD_OUT_GROUP {
+                description "";
+            }
+            enum OFPBAC_MATCH_INCONSISTENT {
+                description "";
+            }
+            enum OFPBAC_UNSUPPORTED_ORDER {
+                description "";
+            }
+            enum OFPBAC_BAD_TAG {
+                description "";
+            }
+            enum OFPBAC_BAD_SET_TYPE {
+                description "";
+            }
+            enum OFPBAC_BAD_SET_LEN {
+                description "";
+            }
+            enum OFPBAC_BAD_SET_ARGUMENT {
+                description "";
+            }
+        }
+        description
+            "ofp_error_msg 'code' values for OFPET_BAD_ACTION.  'data' contains at least
+ the first 64 bytes of the failed request.";
+    }
+    typedef ofp_bad_instruction_code {
+        type enumeration {
+            enum OFPBIC_UNKNOWN_INST {
+                description "";
+            }
+            enum OFPBIC_UNSUP_INST {
+                description "";
+            }
+            enum OFPBIC_BAD_TABLE_ID {
+                description "";
+            }
+            enum OFPBIC_UNSUP_METADATA {
+                description "";
+            }
+            enum OFPBIC_UNSUP_METADATA_MASK {
+                description "";
+            }
+            enum OFPBIC_BAD_EXPERIMENTER {
+                description "";
+            }
+            enum OFPBIC_BAD_EXP_TYPE {
+                description "";
+            }
+            enum OFPBIC_BAD_LEN {
+                description "";
+            }
+            enum OFPBIC_EPERM {
+                description "";
+            }
+        }
+        description
+            "ofp_error_msg 'code' values for OFPET_BAD_INSTRUCTION.  'data' contains at
+ least the first 64 bytes of the failed request.";
+    }
+    typedef ofp_bad_match_code {
+        type enumeration {
+            enum OFPBMC_BAD_TYPE {
+                description "";
+            }
+            enum OFPBMC_BAD_LEN {
+                description "";
+            }
+            enum OFPBMC_BAD_TAG {
+                description "";
+            }
+            enum OFPBMC_BAD_DL_ADDR_MASK {
+                description "";
+            }
+            enum OFPBMC_BAD_NW_ADDR_MASK {
+                description "";
+            }
+            enum OFPBMC_BAD_WILDCARDS {
+                description "";
+            }
+            enum OFPBMC_BAD_FIELD {
+                description "";
+            }
+            enum OFPBMC_BAD_VALUE {
+                description "";
+            }
+            enum OFPBMC_BAD_MASK {
+                description "";
+            }
+            enum OFPBMC_BAD_PREREQ {
+                description "";
+            }
+            enum OFPBMC_DUP_FIELD {
+                description "";
+            }
+            enum OFPBMC_EPERM {
+                description "";
+            }
+        }
+        description
+            "ofp_error_msg 'code' values for OFPET_BAD_MATCH.  'data' contains at least
+ the first 64 bytes of the failed request.";
+    }
+    typedef ofp_flow_mod_failed_code {
+        type enumeration {
+            enum OFPFMFC_UNKNOWN {
+                description "";
+            }
+            enum OFPFMFC_TABLE_FULL {
+                description "";
+            }
+            enum OFPFMFC_BAD_TABLE_ID {
+                description "";
+            }
+            enum OFPFMFC_OVERLAP {
+                description "";
+            }
+            enum OFPFMFC_EPERM {
+                description "";
+            }
+            enum OFPFMFC_BAD_TIMEOUT {
+                description "";
+            }
+            enum OFPFMFC_BAD_COMMAND {
+                description "";
+            }
+            enum OFPFMFC_BAD_FLAGS {
+                description "";
+            }
+        }
+        description
+            "ofp_error_msg 'code' values for OFPET_FLOW_MOD_FAILED.  'data' contains
+ at least the first 64 bytes of the failed request.";
+    }
+    typedef ofp_group_mod_failed_code {
+        type enumeration {
+            enum OFPGMFC_GROUP_EXISTS {
+                description "";
+            }
+            enum OFPGMFC_INVALID_GROUP {
+                description "";
+            }
+            enum OFPGMFC_WEIGHT_UNSUPPORTED {
+                description "";
+            }
+            enum OFPGMFC_OUT_OF_GROUPS {
+                description "";
+            }
+            enum OFPGMFC_OUT_OF_BUCKETS {
+                description "";
+            }
+            enum OFPGMFC_CHAINING_UNSUPPORTED {
+                description "";
+            }
+            enum OFPGMFC_WATCH_UNSUPPORTED {
+                description "";
+            }
+            enum OFPGMFC_LOOP {
+                description "";
+            }
+            enum OFPGMFC_UNKNOWN_GROUP {
+                description "";
+            }
+            enum OFPGMFC_CHAINED_GROUP {
+                description "";
+            }
+            enum OFPGMFC_BAD_TYPE {
+                description "";
+            }
+            enum OFPGMFC_BAD_COMMAND {
+                description "";
+            }
+            enum OFPGMFC_BAD_BUCKET {
+                description "";
+            }
+            enum OFPGMFC_BAD_WATCH {
+                description "";
+            }
+            enum OFPGMFC_EPERM {
+                description "";
+            }
+        }
+        description
+            "ofp_error_msg 'code' values for OFPET_GROUP_MOD_FAILED.  'data' contains
+ at least the first 64 bytes of the failed request.";
+    }
+    typedef ofp_port_mod_failed_code {
+        type enumeration {
+            enum OFPPMFC_BAD_PORT {
+                description "";
+            }
+            enum OFPPMFC_BAD_HW_ADDR {
+                description "";
+            }
+            enum OFPPMFC_BAD_CONFIG {
+                description "";
+            }
+            enum OFPPMFC_BAD_ADVERTISE {
+                description "";
+            }
+            enum OFPPMFC_EPERM {
+                description "";
+            }
+        }
+        description
+            "ofp_error_msg 'code' values for OFPET_PORT_MOD_FAILED.  'data' contains
+ at least the first 64 bytes of the failed request.";
+    }
+    typedef ofp_table_mod_failed_code {
+        type enumeration {
+            enum OFPTMFC_BAD_TABLE {
+                description "";
+            }
+            enum OFPTMFC_BAD_CONFIG {
+                description "";
+            }
+            enum OFPTMFC_EPERM {
+                description "";
+            }
+        }
+        description
+            "ofp_error_msg 'code' values for OFPET_TABLE_MOD_FAILED.  'data' contains
+ at least the first 64 bytes of the failed request.";
+    }
+    typedef ofp_queue_op_failed_code {
+        type enumeration {
+            enum OFPQOFC_BAD_PORT {
+                description "";
+            }
+            enum OFPQOFC_BAD_QUEUE {
+                description "";
+            }
+            enum OFPQOFC_EPERM {
+                description "";
+            }
+        }
+        description
+            "ofp_error msg 'code' values for OFPET_QUEUE_OP_FAILED. 'data' contains
+ at least the first 64 bytes of the failed request";
+    }
+    typedef ofp_switch_config_failed_code {
+        type enumeration {
+            enum OFPSCFC_BAD_FLAGS {
+                description "";
+            }
+            enum OFPSCFC_BAD_LEN {
+                description "";
+            }
+            enum OFPSCFC_EPERM {
+                description "";
+            }
+        }
+        description
+            "ofp_error_msg 'code' values for OFPET_SWITCH_CONFIG_FAILED. 'data' contains
+ at least the first 64 bytes of the failed request.";
+    }
+    typedef ofp_role_request_failed_code {
+        type enumeration {
+            enum OFPRRFC_STALE {
+                description "";
+            }
+            enum OFPRRFC_UNSUP {
+                description "";
+            }
+            enum OFPRRFC_BAD_ROLE {
+                description "";
+            }
+        }
+        description
+            "ofp_error_msg 'code' values for OFPET_ROLE_REQUEST_FAILED. 'data' contains
+ at least the first 64 bytes of the failed request.";
+    }
+    typedef ofp_meter_mod_failed_code {
+        type enumeration {
+            enum OFPMMFC_UNKNOWN {
+                description "";
+            }
+            enum OFPMMFC_METER_EXISTS {
+                description "";
+            }
+            enum OFPMMFC_INVALID_METER {
+                description "";
+            }
+            enum OFPMMFC_UNKNOWN_METER {
+                description "";
+            }
+            enum OFPMMFC_BAD_COMMAND {
+                description "";
+            }
+            enum OFPMMFC_BAD_FLAGS {
+                description "";
+            }
+            enum OFPMMFC_BAD_RATE {
+                description "";
+            }
+            enum OFPMMFC_BAD_BURST {
+                description "";
+            }
+            enum OFPMMFC_BAD_BAND {
+                description "";
+            }
+            enum OFPMMFC_BAD_BAND_VALUE {
+                description "";
+            }
+            enum OFPMMFC_OUT_OF_METERS {
+                description "";
+            }
+            enum OFPMMFC_OUT_OF_BANDS {
+                description "";
+            }
+        }
+        description
+            "ofp_error_msg 'code' values for OFPET_METER_MOD_FAILED.  'data' contains
+ at least the first 64 bytes of the failed request.";
+    }
+    typedef ofp_table_features_failed_code {
+        type enumeration {
+            enum OFPTFFC_BAD_TABLE {
+                description "";
+            }
+            enum OFPTFFC_BAD_METADATA {
+                description "";
+            }
+            enum OFPTFFC_BAD_TYPE {
+                description "";
+            }
+            enum OFPTFFC_BAD_LEN {
+                description "";
+            }
+            enum OFPTFFC_BAD_ARGUMENT {
+                description "";
+            }
+            enum OFPTFFC_EPERM {
+                description "";
+            }
+        }
+        description
+            "ofp_error_msg 'code' values for OFPET_TABLE_FEATURES_FAILED. 'data' contains
+ at least the first 64 bytes of the failed request.";
+    }
+    typedef ofp_multipart_type {
+        type enumeration {
+            enum OFPMP_DESC {
+                description "";
+            }
+            enum OFPMP_FLOW {
+                description "";
+            }
+            enum OFPMP_AGGREGATE {
+                description "";
+            }
+            enum OFPMP_TABLE {
+                description "";
+            }
+            enum OFPMP_PORT_STATS {
+                description "";
+            }
+            enum OFPMP_QUEUE {
+                description "";
+            }
+            enum OFPMP_GROUP {
+                description "";
+            }
+            enum OFPMP_GROUP_DESC {
+                description "";
+            }
+            enum OFPMP_GROUP_FEATURES {
+                description "";
+            }
+            enum OFPMP_METER {
+                description "";
+            }
+            enum OFPMP_METER_CONFIG {
+                description "";
+            }
+            enum OFPMP_METER_FEATURES {
+                description "";
+            }
+            enum OFPMP_TABLE_FEATURES {
+                description "";
+            }
+            enum OFPMP_PORT_DESC {
+                description "";
+            }
+            enum OFPMP_EXPERIMENTER {
+                description "";
+            }
+        }
+        description
+            "";
+    }
+    typedef ofp_multipart_request_flags {
+        type enumeration {
+            enum OFPMPF_REQ_INVALID {
+                description "";
+            }
+            enum OFPMPF_REQ_MORE {
+                description "";
+            }
+        }
+        description
+            "Backward compatibility with 1.3.1 - avoid breaking the API.#define ofp_multipart_types ofp_multipart_type";
+    }
+    typedef ofp_multipart_reply_flags {
+        type enumeration {
+            enum OFPMPF_REPLY_INVALID {
+                description "";
+            }
+            enum OFPMPF_REPLY_MORE {
+                description "";
+            }
+        }
+        description
+            "";
+    }
+    typedef ofp_table_feature_prop_type {
+        type enumeration {
+            enum OFPTFPT_INSTRUCTIONS {
+                description "";
+            }
+            enum OFPTFPT_INSTRUCTIONS_MISS {
+                description "";
+            }
+            enum OFPTFPT_NEXT_TABLES {
+                description "";
+            }
+            enum OFPTFPT_NEXT_TABLES_MISS {
+                description "";
+            }
+            enum OFPTFPT_WRITE_ACTIONS {
+                description "";
+            }
+            enum OFPTFPT_WRITE_ACTIONS_MISS {
+                description "";
+            }
+            enum OFPTFPT_APPLY_ACTIONS {
+                description "";
+            }
+            enum OFPTFPT_APPLY_ACTIONS_MISS {
+                description "";
+            }
+            enum OFPTFPT_MATCH {
+                description "";
+            }
+            enum OFPTFPT_WILDCARDS {
+                description "";
+            }
+            enum OFPTFPT_WRITE_SETFIELD {
+                description "";
+            }
+            enum OFPTFPT_WRITE_SETFIELD_MISS {
+                description "";
+            }
+            enum OFPTFPT_APPLY_SETFIELD {
+                description "";
+            }
+            enum OFPTFPT_APPLY_SETFIELD_MISS {
+                description "";
+            }
+            enum OFPTFPT_EXPERIMENTER {
+                description "";
+            }
+            enum OFPTFPT_EXPERIMENTER_MISS {
+                description "";
+            }
+        }
+        description
+            "Table Feature property types.
+ Low order bit cleared indicates a property for a regular Flow Entry.
+ Low order bit set indicates a property for the Table-Miss Flow Entry.";
+    }
+    typedef ofp_group_capabilities {
+        type enumeration {
+            enum OFPGFC_INVALID {
+                description "";
+            }
+            enum OFPGFC_SELECT_WEIGHT {
+                description "";
+            }
+            enum OFPGFC_SELECT_LIVENESS {
+                description "";
+            }
+            enum OFPGFC_CHAINING {
+                description "";
+            }
+            enum OFPGFC_CHAINING_CHECKS {
+                description "";
+            }
+        }
+        description
+            "Group configuration flagsBackward compatibility with 1.3.1 - avoid breaking the API.#define ofp_group_desc_stats ofp_group_desc";
+    }
+    typedef ofp_queue_properties {
+        type enumeration {
+            enum OFPQT_INVALID {
+                description "";
+            }
+            enum OFPQT_MIN_RATE {
+                description "";
+            }
+            enum OFPQT_MAX_RATE {
+                description "";
+            }
+            enum OFPQT_EXPERIMENTER {
+                description "";
+            }
+        }
+        description
+            "All ones is used to indicate all queues in a port (for stats retrieval).#define OFPQ_ALL      0xffffffff
+Min rate > 1000 means not configured.#define OFPQ_MIN_RATE_UNCFG      0xffff
+Max rate > 1000 means not configured.#define OFPQ_MAX_RATE_UNCFG      0xffff";
+    }
+    typedef ofp_controller_role {
+        type enumeration {
+            enum OFPCR_ROLE_NOCHANGE {
+                description "";
+            }
+            enum OFPCR_ROLE_EQUAL {
+                description "";
+            }
+            enum OFPCR_ROLE_MASTER {
+                description "";
+            }
+            enum OFPCR_ROLE_SLAVE {
+                description "";
+            }
+        }
+        description
+            "Controller roles.Configures the  role  of the sending controller.  The default role is:
+
+    - Equal (OFPCR_ROLE_EQUAL), which allows the controller access to all
+      OpenFlow features. All controllers have equal responsibility.
+
+ The other possible roles are a related pair:
+
+    - Master (OFPCR_ROLE_MASTER) is equivalent to Equal, except that there
+      may be at most one Master controller at a time: when a controller
+      configures itself as Master, any existing Master is demoted to the
+      Slave role.
+
+    - Slave (OFPCR_ROLE_SLAVE) allows the controller read-only access to
+      OpenFlow features.  In particular attempts to modify the flow table
+      will be rejected with an OFPBRC_EPERM error.
+
+      Slave controllers do not receive OFPT_PACKET_IN or OFPT_FLOW_REMOVED
+      messages, but they do receive OFPT_PORT_STATUS messages.";
+    }
+
+    container ofp_header {
+        description
+            "Header on all OpenFlow packets.";
+        leaf version {
+            type  uint32; 
+            description
+                "OFP_VERSION.";
+        }
+
+        leaf type {
+            type  ofp_type;
+
+            description
+                "One of the OFPT_ constants.";
+        }
+
+        leaf xid {
+            type  uint32; 
+            description
+                "Transaction id associated with this packet.
+Replies use the same id as was in the request
+to facilitate pairing.";
+        }
+
+    }
+
+    grouping ofp_hello_elem_header {
+        description
+            "Common header for all Hello Elements";
+        leaf type {
+            type  ofp_hello_elem_type;
+
+            description
+                "One of OFPHET_ .";
+        }
+
+        container versionbitmap {
+            uses  ofp_hello_elem_versionbitmap;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping ofp_hello_elem_versionbitmap {
+        description
+            "Version bitmap Hello Element";
+        list bitmaps {
+            key "bitmaps";
+            leaf bitmaps {
+                type  uint32; 
+                description
+                    "List of bitmaps - supported versions";
+            }
+            description
+                "List of bitmaps - supported versions";
+        }
+
+    }
+
+    container ofp_hello {
+        description
+            "OFPT_HELLO.  This message includes zero or more hello elements having
+ variable size. Unknown elements types must be ignored skipped, to allow
+ for future extensions.ofp_header header;";
+        list elements {
+            key "type";
+            uses  ofp_hello_elem_header;
+
+            description
+                "Hello element list0 or more";
+        }
+
+    }
+
+    container ofp_switch_config {
+        description
+            "Switch configuration.";
+        leaf flags {
+            type  uint32; 
+            description
+                "ofp_header header;
+Bitmap of OFPC_  flags.";
+        }
+
+        leaf miss_send_len {
+            type  uint32; 
+            description
+                "Max bytes of packet that datapath
+should send to the controller. See
+ofp_controller_max_len for valid values.";
+        }
+
+    }
+
+    container ofp_table_mod {
+        description
+            "Configure Modify behavior of a flow table";
+        leaf table_id {
+            type  uint32; 
+            description
+                "ofp_header header;
+ID of the table, OFPTT_ALL indicates all tables";
+        }
+
+        leaf config {
+            type  uint32; 
+            description
+                "Bitmap of OFPTC_  flags";
+        }
+
+    }
+
+    grouping ofp_port {
+        description
+            "Description of a port";
+        leaf port_no {
+            type  uint32; 
+            description
+                "";
+        }
+
+        list hw_addr {
+            key "hw_addr";
+            leaf hw_addr {
+                type  uint32; 
+                description
+                    " OFP_ETH_ALEN ;";
+            }
+            description
+                " OFP_ETH_ALEN ;";
+        }
+
+        leaf name {
+            type  string; 
+            description
+                "Null-terminated";
+        }
+
+        leaf config {
+            type  uint32; 
+            description
+                "Bitmap of OFPPC_  flags.";
+        }
+
+        leaf state {
+            type  uint32; 
+            description
+                "Bitmap of OFPPS_  flags.";
+        }
+
+        leaf curr {
+            type  uint32; 
+            description
+                "Bitmaps of OFPPF_  that describe features.  All bits zeroed if
+ unsupported or unavailable.Current features.";
+        }
+
+        leaf advertised {
+            type  uint32; 
+            description
+                "Features being advertised by the port.";
+        }
+
+        leaf supported {
+            type  uint32; 
+            description
+                "Features supported by the port.";
+        }
+
+        leaf peer {
+            type  uint32; 
+            description
+                "Features advertised by peer.";
+        }
+
+        leaf curr_speed {
+            type  uint32; 
+            description
+                "Current port bitrate in kbps.";
+        }
+
+        leaf max_speed {
+            type  uint32; 
+            description
+                "Max port bitrate in kbps";
+        }
+
+    }
+
+    grouping ofp_switch_features {
+        description
+            "Switch features.";
+        leaf datapath_id {
+            type  uint64; 
+            description
+                "ofp_header header;
+Datapath unique ID.  The lower 48-bits are for
+a MAC address, while the upper 16-bits are
+implementer-defined.";
+        }
+
+        leaf n_buffers {
+            type  uint32; 
+            description
+                "Max packets buffered at once.";
+        }
+
+        leaf n_tables {
+            type  uint32; 
+            description
+                "Number of tables supported by datapath.";
+        }
+
+        leaf auxiliary_id {
+            type  uint32; 
+            description
+                "Identify auxiliary connections";
+        }
+
+        leaf capabilities {
+            type  uint32; 
+            description
+                "Features.Bitmap of support  ofp_capabilities .";
+        }
+
+    }
+
+    container ofp_port_status {
+        description
+            "A physical port has changed in the datapath";
+        leaf reason {
+            type  ofp_port_reason;
+
+            description
+                "ofp_header header;
+One of OFPPR_ .";
+        }
+
+        container desc {
+            uses  ofp_port;
+
+            description
+                "";
+        }
+
+    }
+
+    container ofp_port_mod {
+        description
+            "Modify behavior of the physical port";
+        leaf port_no {
+            type  uint32; 
+            description
+                "ofp_header header;";
+        }
+
+        list hw_addr {
+            key "hw_addr";
+            leaf hw_addr {
+                type  uint32; 
+                description
+                    " OFP_ETH_ALEN ;";
+            }
+            description
+                " OFP_ETH_ALEN ;";
+        }
+
+        leaf config {
+            type  uint32; 
+            description
+                "The hardware address is not
+configurable.  This is used to
+sanity-check the request, so it must
+be the same as returned in an
+ofp_port struct.Bitmap of OFPPC_  flags.";
+        }
+
+        leaf mask {
+            type  uint32; 
+            description
+                "Bitmap of OFPPC_  flags to be changed.";
+        }
+
+        leaf advertise {
+            type  uint32; 
+            description
+                "Bitmap of OFPPF_ .  Zero all bits to prevent
+any action taking place.";
+        }
+
+    }
+
+    grouping ofp_match {
+        description
+            "Fields to match against flows";
+        leaf type {
+            type  ofp_match_type;
+
+            description
+                "One of OFPMT_ ";
+        }
+
+        list oxm_fields {
+            key "oxm_class";
+            uses  ofp_oxm_field;
+
+            description
+                "0 or more";
+        }
+
+    }
+
+    grouping ofp_oxm_field {
+        description
+            "OXM Flow match fields";
+        leaf oxm_class {
+            type  ofp_oxm_class;
+
+            description
+                "";
+        }
+
+        container ofb_field {
+            uses  ofp_oxm_ofb_field;
+
+            description
+                "2 and 3 reserved for NXM_0 and NXM-1 OXM classes";
+        }
+
+        container experimenter_field {
+            uses  ofp_oxm_experimenter_field;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping ofp_oxm_ofb_field {
+        description
+            "OXM OpenFlow Basic Match Field";
+        leaf type {
+            type  oxm_ofb_field_types;
+
+            description
+                "";
+        }
+
+        leaf has_mask {
+            type  boolean; 
+            description
+                "";
+        }
+
+        leaf port {
+            type  uint32; 
+            description
+                "#define OXM_OF_IN_PORT    OXM_HEADER  (0x8000, OFPXMT_OFB_IN_PORT, 4)
+Used for OFPXMT_OFB_IN_PORTOpenFlow port on which the packet was received.
+ May be a physical port, a logical port, or the reserved port OFPP_LOCAL
+
+ Prereqs: None.
+
+ Format: 32-bit integer in network byte order.
+
+ Masking: Not maskable.";
+        }
+
+        leaf physical_port {
+            type  uint32; 
+            description
+                "#define OXM_OF_IN_PHY_PORT OXM_HEADER  (0x8000, OFPXMT_OFB_IN_PHY_PORT, 4)
+Used for OFPXMT_OF_IN_PHY_PORTPhysical port on which the packet was received.
+
+ Consider a packet received on a tunnel interface defined over a link
+ aggregation group (LAG) with two physical port members.  If the tunnel
+ interface is the logical port bound to OpenFlow.  In this case,
+ OFPXMT_OF_IN_PORT is the tunnel's port number and OFPXMT_OF_IN_PHY_PORT is
+ the physical port number of the LAG on which the tunnel is configured.
+
+ When a packet is received directly on a physical port and not processed by a
+ logical port, OFPXMT_OF_IN_PORT and OFPXMT_OF_IN_PHY_PORT have the same
+ value.
+
+ This field is usually not available in a regular match and only available
+ in ofp_packet_in messages when it's different from OXM_OF_IN_PORT.
+
+ Prereqs: OXM_OF_IN_PORT must be present.
+
+ Format: 32-bit integer in network byte order.
+
+ Masking: Not maskable.";
+        }
+
+        leaf table_metadata {
+            type  uint64; 
+            description
+                "#define OXM_OF_METADATA   OXM_HEADER  (0x8000, OFPXMT_OFB_METADATA, 8)
+#define OXM_OF_METADATA_W OXM_HEADER_W(0x8000, OFPXMT_OFB_METADATA, 8)
+Used for OFPXMT_OFB_METADATATable metadata.
+
+ Prereqs: None.
+
+ Format: 64-bit integer in network byte order.
+
+ Masking: Arbitrary masks.";
+        }
+
+        leaf eth_dst {
+            type  binary; 
+            description
+                "#define OXM_OF_ETH_DST    OXM_HEADER  (0x8000, OFPXMT_OFB_ETH_DST, 6)
+#define OXM_OF_ETH_DST_W  OXM_HEADER_W(0x8000, OFPXMT_OFB_ETH_DST, 6)
+#define OXM_OF_ETH_SRC    OXM_HEADER  (0x8000, OFPXMT_OFB_ETH_SRC, 6)
+#define OXM_OF_ETH_SRC_W  OXM_HEADER_W(0x8000, OFPXMT_OFB_ETH_SRC, 6)
+Used for OFPXMT_OFB_ETH_DST (exactly 6 bytes)Source or destination address in Ethernet header.
+
+ Prereqs: None.
+
+ Format: 48-bit Ethernet MAC address.
+
+ Masking: Arbitrary masks.";
+        }
+
+        leaf eth_src {
+            type  binary; 
+            description
+                "Used for OFPXMT_OFB_ETH_SRC (exactly 6 bytes)";
+        }
+
+        leaf eth_type {
+            type  uint32; 
+            description
+                "#define OXM_OF_ETH_TYPE   OXM_HEADER  (0x8000, OFPXMT_OFB_ETH_TYPE,2)
+Used for OFPXMT_OFB_ETH_TYPEPacket's Ethernet type.
+
+ Prereqs: None.
+
+ Format: 16-bit integer in network byte order.
+
+ Masking: Not maskable.";
+        }
+
+        leaf vlan_vid {
+            type  uint32; 
+            description
+                "#define OXM_OF_VLAN_VID   OXM_HEADER  (0x8000, OFPXMT_OFB_VLAN_VID, 2)
+#define OXM_OF_VLAN_VID_W OXM_HEADER_W(0x8000, OFPXMT_OFB_VLAN_VID, 2)
+Used for OFPXMT_OFB_VLAN_VID802.1Q VID.
+
+ For a packet with an 802.1Q header, this is the VLAN-ID (VID) from the
+ outermost tag, with the CFI bit forced to 1. For a packet with no 802.1Q
+ header, this has value OFPVID_NONE.
+
+ Prereqs: None.
+
+ Format: 16-bit integer in network byte order with bit 13 indicating
+ presence of VLAN header and 3 most-significant bits forced to 0.
+ Only the lower 13 bits have meaning.
+
+ Masking: Arbitrary masks.
+
+ This field can be used in various ways:
+
+   - If it is not constrained at all, the nx_match matches packets without
+     an 802.1Q header or with an 802.1Q header that has any VID value.
+
+   - Testing for an exact match with 0x0 matches only packets without
+     an 802.1Q header.
+
+   - Testing for an exact match with a VID value with CFI=1 matches packets
+     that have an 802.1Q header with a specified VID.
+
+   - Testing for an exact match with a nonzero VID value with CFI=0 does
+     not make sense.  The switch may reject this combination.
+
+   - Testing with nxm_value=0, nxm_mask=0x0fff matches packets with no 802.1Q
+     header or with an 802.1Q header with a VID of 0.
+
+   - Testing with nxm_value=0x1000, nxm_mask=0x1000 matches packets with
+     an 802.1Q header that has any VID value.";
+        }
+
+        leaf vlan_pcp {
+            type  uint32; 
+            description
+                "#define OXM_OF_VLAN_PCP   OXM_HEADER  (0x8000, OFPXMT_OFB_VLAN_PCP, 1)
+Used for OFPXMT_OFB_VLAN_PCP802.1Q PCP.
+
+ For a packet with an 802.1Q header, this is the VLAN-PCP from the
+ outermost tag.  For a packet with no 802.1Q header, this has value
+ 0.
+
+ Prereqs: OXM_OF_VLAN_VID must be different from OFPVID_NONE.
+
+ Format: 8-bit integer with 5 most-significant bits forced to 0.
+ Only the lower 3 bits have meaning.
+
+ Masking: Not maskable.";
+        }
+
+        leaf ip_dscp {
+            type  uint32; 
+            description
+                "#define OXM_OF_IP_DSCP     OXM_HEADER  (0x8000, OFPXMT_OFB_IP_DSCP, 1)
+Used for OFPXMT_OFB_IP_DSCPThe Diff Serv Code Point (DSCP) bits of the IP header.
+ Part of the IPv4 ToS field or the IPv6 Traffic Class field.
+
+ Prereqs: OXM_OF_ETH_TYPE must be either 0x0800 or 0x86dd.
+
+ Format: 8-bit integer with 2 most-significant bits forced to 0.
+ Only the lower 6 bits have meaning.
+
+ Masking: Not maskable.";
+        }
+
+        leaf ip_ecn {
+            type  uint32; 
+            description
+                "#define OXM_OF_IP_ECN     OXM_HEADER  (0x8000, OFPXMT_OFB_IP_ECN, 1)
+Used for OFPXMT_OFB_IP_ECNThe ECN bits of the IP header.
+ Part of the IPv4 ToS field or the IPv6 Traffic Class field.
+
+ Prereqs: OXM_OF_ETH_TYPE must be either 0x0800 or 0x86dd.
+
+ Format: 8-bit integer with 6 most-significant bits forced to 0.
+ Only the lower 2 bits have meaning.
+
+ Masking: Not maskable.";
+        }
+
+        leaf ip_proto {
+            type  uint32; 
+            description
+                "#define OXM_OF_IP_PROTO   OXM_HEADER  (0x8000, OFPXMT_OFB_IP_PROTO, 1)
+Used for OFPXMT_OFB_IP_PROTOThe  protocol  byte in the IP header.
+
+ Prereqs: OXM_OF_ETH_TYPE must be either 0x0800 or 0x86dd.
+
+ Format: 8-bit integer.
+
+ Masking: Not maskable.";
+        }
+
+        leaf ipv4_src {
+            type  uint32; 
+            description
+                "#define OXM_OF_IPV4_SRC     OXM_HEADER  (0x8000, OFPXMT_OFB_IPV4_SRC, 4)
+#define OXM_OF_IPV4_SRC_W   OXM_HEADER_W(0x8000, OFPXMT_OFB_IPV4_SRC, 4)
+#define OXM_OF_IPV4_DST     OXM_HEADER  (0x8000, OFPXMT_OFB_IPV4_DST, 4)
+#define OXM_OF_IPV4_DST_W   OXM_HEADER_W(0x8000, OFPXMT_OFB_IPV4_DST, 4)
+Used for OFPXMT_OFB_IPV4_SRCThe source or destination address in the IP header.
+
+ Prereqs: OXM_OF_ETH_TYPE must match 0x0800 exactly.
+
+ Format: 32-bit integer in network byte order.
+
+ Masking: Arbitrary masks.";
+        }
+
+        leaf ipv4_dst {
+            type  uint32; 
+            description
+                "Used for OFPXMT_OFB_IPV4_DST";
+        }
+
+        leaf tcp_src {
+            type  uint32; 
+            description
+                "#define OXM_OF_TCP_SRC    OXM_HEADER  (0x8000, OFPXMT_OFB_TCP_SRC, 2)
+#define OXM_OF_TCP_DST    OXM_HEADER  (0x8000, OFPXMT_OFB_TCP_DST, 2)
+Used for OFPXMT_OFB_TCP_SRCThe source or destination port in the TCP header.
+
+ Prereqs:
+   OXM_OF_ETH_TYPE must be either 0x0800 or 0x86dd.
+   OXM_OF_IP_PROTO must match 6 exactly.
+
+ Format: 16-bit integer in network byte order.
+
+ Masking: Not maskable.";
+        }
+
+        leaf tcp_dst {
+            type  uint32; 
+            description
+                "Used for OFPXMT_OFB_TCP_DST";
+        }
+
+        leaf udp_src {
+            type  uint32; 
+            description
+                "#define OXM_OF_UDP_SRC    OXM_HEADER  (0x8000, OFPXMT_OFB_UDP_SRC, 2)
+#define OXM_OF_UDP_DST    OXM_HEADER  (0x8000, OFPXMT_OFB_UDP_DST, 2)
+Used for OFPXMT_OFB_UDP_SRCThe source or destination port in the UDP header.
+
+ Prereqs:
+   OXM_OF_ETH_TYPE must match either 0x0800 or 0x86dd.
+   OXM_OF_IP_PROTO must match 17 exactly.
+
+ Format: 16-bit integer in network byte order.
+
+ Masking: Not maskable.";
+        }
+
+        leaf udp_dst {
+            type  uint32; 
+            description
+                "Used for OFPXMT_OFB_UDP_DST";
+        }
+
+        leaf sctp_src {
+            type  uint32; 
+            description
+                "#define OXM_OF_SCTP_SRC   OXM_HEADER  (0x8000, OFPXMT_OFB_SCTP_SRC, 2)
+#define OXM_OF_SCTP_DST   OXM_HEADER  (0x8000, OFPXMT_OFB_SCTP_DST, 2)
+Used for OFPXMT_OFB_SCTP_SRCThe source or destination port in the SCTP header.
+
+ Prereqs:
+   OXM_OF_ETH_TYPE must match either 0x0800 or 0x86dd.
+   OXM_OF_IP_PROTO must match 132 exactly.
+
+ Format: 16-bit integer in network byte order.
+
+ Masking: Not maskable.";
+        }
+
+        leaf sctp_dst {
+            type  uint32; 
+            description
+                "Used for OFPXMT_OFB_SCTP_DST";
+        }
+
+        leaf icmpv4_type {
+            type  uint32; 
+            description
+                "#define OXM_OF_ICMPV4_TYPE  OXM_HEADER  (0x8000, OFPXMT_OFB_ICMPV4_TYPE, 1)
+#define OXM_OF_ICMPV4_CODE  OXM_HEADER  (0x8000, OFPXMT_OFB_ICMPV4_CODE, 1)
+Used for OFPXMT_OFB_ICMPV4_TYPEThe type or code in the ICMP header.
+
+ Prereqs:
+   OXM_OF_ETH_TYPE must match 0x0800 exactly.
+   OXM_OF_IP_PROTO must match 1 exactly.
+
+ Format: 8-bit integer.
+
+ Masking: Not maskable.";
+        }
+
+        leaf icmpv4_code {
+            type  uint32; 
+            description
+                "Used for OFPXMT_OFB_ICMPV4_CODE";
+        }
+
+        leaf arp_op {
+            type  uint32; 
+            description
+                "#define OXM_OF_ARP_OP     OXM_HEADER  (0x8000, OFPXMT_OFB_ARP_OP, 2)
+Used for OFPXMT_OFB_ARP_OPARP opcode.
+
+ For an Ethernet+IP ARP packet, the opcode in the ARP header.  Always 0
+ otherwise.
+
+ Prereqs: OXM_OF_ETH_TYPE must match 0x0806 exactly.
+
+ Format: 16-bit integer in network byte order.
+
+ Masking: Not maskable.";
+        }
+
+        leaf arp_spa {
+            type  uint32; 
+            description
+                "#define OXM_OF_ARP_SPA    OXM_HEADER  (0x8000, OFPXMT_OFB_ARP_SPA, 4)
+#define OXM_OF_ARP_SPA_W  OXM_HEADER_W(0x8000, OFPXMT_OFB_ARP_SPA, 4)
+#define OXM_OF_ARP_TPA    OXM_HEADER  (0x8000, OFPXMT_OFB_ARP_TPA, 4)
+#define OXM_OF_ARP_TPA_W  OXM_HEADER_W(0x8000, OFPXMT_OFB_ARP_TPA, 4)
+For OFPXMT_OFB_ARP_SPAFor an Ethernet+IP ARP packet, the source or target protocol address
+ in the ARP header.  Always 0 otherwise.
+
+ Prereqs: OXM_OF_ETH_TYPE must match 0x0806 exactly.
+
+ Format: 32-bit integer in network byte order.
+
+ Masking: Arbitrary masks.";
+        }
+
+        leaf arp_tpa {
+            type  uint32; 
+            description
+                "For OFPXMT_OFB_ARP_TPA";
+        }
+
+        leaf arp_sha {
+            type  binary; 
+            description
+                "#define OXM_OF_ARP_SHA    OXM_HEADER   (0x8000, OFPXMT_OFB_ARP_SHA, 6)
+#define OXM_OF_ARP_SHA_W  OXM_HEADER_W (0x8000, OFPXMT_OFB_ARP_SHA, 6)
+#define OXM_OF_ARP_THA    OXM_HEADER   (0x8000, OFPXMT_OFB_ARP_THA, 6)
+#define OXM_OF_ARP_THA_W  OXM_HEADER_W (0x8000, OFPXMT_OFB_ARP_THA, 6)
+For OFPXMT_OFB_ARP_SHA (6 bytes)For an Ethernet+IP ARP packet, the source or target hardware address
+ in the ARP header.  Always 0 otherwise.
+
+ Prereqs: OXM_OF_ETH_TYPE must match 0x0806 exactly.
+
+ Format: 48-bit Ethernet MAC address.
+
+ Masking: Not maskable.";
+        }
+
+        leaf arp_tha {
+            type  binary; 
+            description
+                "For OFPXMT_OFB_ARP_THA (6 bytes)";
+        }
+
+        leaf ipv6_src {
+            type  binary; 
+            description
+                "#define OXM_OF_IPV6_SRC    OXM_HEADER  (0x8000, OFPXMT_OFB_IPV6_SRC, 16)
+#define OXM_OF_IPV6_SRC_W  OXM_HEADER_W(0x8000, OFPXMT_OFB_IPV6_SRC, 16)
+#define OXM_OF_IPV6_DST    OXM_HEADER  (0x8000, OFPXMT_OFB_IPV6_DST, 16)
+#define OXM_OF_IPV6_DST_W  OXM_HEADER_W(0x8000, OFPXMT_OFB_IPV6_DST, 16)
+For OFPXMT_OFB_IPV6_SRCThe source or destination address in the IPv6 header.
+
+ Prereqs: OXM_OF_ETH_TYPE must match 0x86dd exactly.
+
+ Format: 128-bit IPv6 address.
+
+ Masking: Arbitrary masks.";
+        }
+
+        leaf ipv6_dst {
+            type  binary; 
+            description
+                "For OFPXMT_OFB_IPV6_DST";
+        }
+
+        leaf ipv6_flabel {
+            type  uint32; 
+            description
+                "#define OXM_OF_IPV6_FLABEL   OXM_HEADER  (0x8000, OFPXMT_OFB_IPV6_FLABEL, 4)
+#define OXM_OF_IPV6_FLABEL_W OXM_HEADER_W(0x8000, OFPXMT_OFB_IPV6_FLABEL, 4)
+For OFPXMT_OFB_IPV6_FLABELThe IPv6 Flow Label
+
+ Prereqs:
+   OXM_OF_ETH_TYPE must match 0x86dd exactly
+
+ Format: 32-bit integer with 12 most-significant bits forced to 0.
+ Only the lower 20 bits have meaning.
+
+ Masking: Arbitrary masks.";
+        }
+
+        leaf icmpv6_type {
+            type  uint32; 
+            description
+                "#define OXM_OF_ICMPV6_TYPE OXM_HEADER  (0x8000, OFPXMT_OFB_ICMPV6_TYPE, 1)
+#define OXM_OF_ICMPV6_CODE OXM_HEADER  (0x8000, OFPXMT_OFB_ICMPV6_CODE, 1)
+For OFPXMT_OFB_ICMPV6_TYPEThe type or code in the ICMPv6 header.
+
+ Prereqs:
+   OXM_OF_ETH_TYPE must match 0x86dd exactly.
+   OXM_OF_IP_PROTO must match 58 exactly.
+
+ Format: 8-bit integer.
+
+ Masking: Not maskable.";
+        }
+
+        leaf icmpv6_code {
+            type  uint32; 
+            description
+                "For OFPXMT_OFB_ICMPV6_CODE";
+        }
+
+        leaf ipv6_nd_target {
+            type  binary; 
+            description
+                "#define OXM_OF_IPV6_ND_TARGET OXM_HEADER  
+    (0x8000, OFPXMT_OFB_IPV6_ND_TARGET, 16)
+For OFPXMT_OFB_IPV6_ND_TARGETThe target address in an IPv6 Neighbor Discovery message.
+
+ Prereqs:
+   OXM_OF_ETH_TYPE must match 0x86dd exactly.
+   OXM_OF_IP_PROTO must match 58 exactly.
+   OXM_OF_ICMPV6_TYPE must be either 135 or 136.
+
+ Format: 128-bit IPv6 address.
+
+ Masking: Not maskable.";
+        }
+
+        leaf ipv6_nd_ssl {
+            type  binary; 
+            description
+                "#define OXM_OF_IPV6_ND_SLL  OXM_HEADER  (0x8000, OFPXMT_OFB_IPV6_ND_SLL, 6)
+For OFPXMT_OFB_IPV6_ND_SLLThe source link-layer address option in an IPv6 Neighbor Discovery
+ message.
+
+ Prereqs:
+   OXM_OF_ETH_TYPE must match 0x86dd exactly.
+   OXM_OF_IP_PROTO must match 58 exactly.
+   OXM_OF_ICMPV6_TYPE must be exactly 135.
+
+ Format: 48-bit Ethernet MAC address.
+
+ Masking: Not maskable.";
+        }
+
+        leaf ipv6_nd_tll {
+            type  binary; 
+            description
+                "#define OXM_OF_IPV6_ND_TLL  OXM_HEADER  (0x8000, OFPXMT_OFB_IPV6_ND_TLL, 6)
+For OFPXMT_OFB_IPV6_ND_TLLThe target link-layer address option in an IPv6 Neighbor Discovery
+ message.
+
+ Prereqs:
+   OXM_OF_ETH_TYPE must match 0x86dd exactly.
+   OXM_OF_IP_PROTO must match 58 exactly.
+   OXM_OF_ICMPV6_TYPE must be exactly 136.
+
+ Format: 48-bit Ethernet MAC address.
+
+ Masking: Not maskable.";
+        }
+
+        leaf mpls_label {
+            type  uint32; 
+            description
+                "#define OXM_OF_MPLS_LABEL  OXM_HEADER  (0x8000, OFPXMT_OFB_MPLS_LABEL, 4)
+For OFPXMT_OFB_MPLS_LABELThe LABEL in the first MPLS shim header.
+
+ Prereqs:
+   OXM_OF_ETH_TYPE must match 0x8847 or 0x8848 exactly.
+
+ Format: 32-bit integer in network byte order with 12 most-significant
+ bits forced to 0. Only the lower 20 bits have meaning.
+
+ Masking: Not maskable.";
+        }
+
+        leaf mpls_tc {
+            type  uint32; 
+            description
+                "#define OXM_OF_MPLS_TC     OXM_HEADER  (0x8000, OFPXMT_OFB_MPLS_TC, 1)
+For OFPXMT_OFB_MPLS_TCThe TC in the first MPLS shim header.
+
+ Prereqs:
+   OXM_OF_ETH_TYPE must match 0x8847 or 0x8848 exactly.
+
+ Format: 8-bit integer with 5 most-significant bits forced to 0.
+ Only the lower 3 bits have meaning.
+
+ Masking: Not maskable.";
+        }
+
+        leaf mpls_bos {
+            type  uint32; 
+            description
+                "#define OXM_OF_MPLS_BOS     OXM_HEADER  (0x8000, OFPXMT_OFB_MPLS_BOS, 1)
+For OFPXMT_OFB_MPLS_BOSThe BoS bit in the first MPLS shim header.
+
+ Prereqs:
+   OXM_OF_ETH_TYPE must match 0x8847 or 0x8848 exactly.
+
+ Format: 8-bit integer with 7 most-significant bits forced to 0.
+ Only the lowest bit have a meaning.
+
+ Masking: Not maskable.";
+        }
+
+        leaf pbb_isid {
+            type  uint32; 
+            description
+                "#define OXM_OF_PBB_ISID   OXM_HEADER  (0x8000, OFPXMT_OFB_PBB_ISID, 3)
+#define OXM_OF_PBB_ISID_W OXM_HEADER_W(0x8000, OFPXMT_OFB_PBB_ISID, 3)
+For OFPXMT_OFB_PBB_ISIDIEEE 802.1ah I-SID.
+
+ For a packet with a PBB header, this is the I-SID from the
+ outermost service tag.
+
+ Prereqs:
+   OXM_OF_ETH_TYPE must match 0x88E7 exactly.
+
+ Format: 24-bit integer in network byte order.
+
+ Masking: Arbitrary masks.";
+        }
+
+        leaf tunnel_id {
+            type  uint64; 
+            description
+                "#define OXM_OF_TUNNEL_ID    OXM_HEADER  (0x8000, OFPXMT_OFB_TUNNEL_ID, 8)
+#define OXM_OF_TUNNEL_ID_W  OXM_HEADER_W(0x8000, OFPXMT_OFB_TUNNEL_ID, 8)
+For OFPXMT_OFB_TUNNEL_IDLogical Port Metadata.
+
+ Metadata associated with a logical port.
+ If the logical port performs encapsulation and decapsulation, this
+ is the demultiplexing field from the encapsulation header.
+ For example, for a packet received via GRE tunnel including a (32-bit) key,
+ the key is stored in the low 32-bits and the high bits are zeroed.
+ For a MPLS logical port, the low 20 bits represent the MPLS Label.
+ For a VxLAN logical port, the low 24 bits represent the VNI.
+ If the packet is not received through a logical port, the value is 0.
+
+ Prereqs: None.
+
+ Format: 64-bit integer in network byte order.
+
+ Masking: Arbitrary masks.";
+        }
+
+        leaf ipv6_exthdr {
+            type  uint32; 
+            description
+                "#define OXM_OF_IPV6_EXTHDR   OXM_HEADER  (0x8000, OFPXMT_OFB_IPV6_EXTHDR, 2)
+#define OXM_OF_IPV6_EXTHDR_W OXM_HEADER_W(0x8000, OFPXMT_OFB_IPV6_EXTHDR, 2)
+For OFPXMT_OFB_IPV6_EXTHDRThe IPv6 Extension Header pseudo-field.
+
+ Prereqs:
+   OXM_OF_ETH_TYPE must match 0x86dd exactly
+
+ Format: 16-bit integer with 7 most-significant bits forced to 0.
+ Only the lower 9 bits have meaning.
+
+ Masking: Maskable.";
+        }
+
+        leaf table_metadata_mask {
+            type  uint64; 
+            description
+                "For OFPXMT_OFB_METADATA";
+        }
+
+        leaf eth_dst_mask {
+            type  binary; 
+            description
+                "For OFPXMT_OFB_ETH_DST (exactly 6 bytes)";
+        }
+
+        leaf eth_src_mask {
+            type  binary; 
+            description
+                "For OFPXMT_OFB_ETH_SRC (exactly 6 bytes)";
+        }
+
+        leaf vlan_vid_mask {
+            type  uint32; 
+            description
+                "For OFPXMT_OFB_VLAN_VID";
+        }
+
+        leaf ipv4_src_mask {
+            type  uint32; 
+            description
+                "For OFPXMT_OFB_IPV4_SRC";
+        }
+
+        leaf ipv4_dst_mask {
+            type  uint32; 
+            description
+                "For OFPXMT_OFB_IPV4_DST";
+        }
+
+        leaf arp_spa_mask {
+            type  uint32; 
+            description
+                "For OFPXMT_OFB_ARP_SPA";
+        }
+
+        leaf arp_tpa_mask {
+            type  uint32; 
+            description
+                "For OFPXMT_OFB_ARP_TPA";
+        }
+
+        leaf ipv6_src_mask {
+            type  binary; 
+            description
+                "For OFPXMT_OFB_IPV6_SRC";
+        }
+
+        leaf ipv6_dst_mask {
+            type  binary; 
+            description
+                "For OFPXMT_OFB_IPV6_DST";
+        }
+
+        leaf ipv6_flabel_mask {
+            type  uint32; 
+            description
+                "For OFPXMT_OFB_IPV6_FLABEL";
+        }
+
+        leaf pbb_isid_mask {
+            type  uint32; 
+            description
+                "For OFPXMT_OFB_PBB_ISID";
+        }
+
+        leaf tunnel_id_mask {
+            type  uint64; 
+            description
+                "For OFPXMT_OFB_TUNNEL_ID";
+        }
+
+        leaf ipv6_exthdr_mask {
+            type  uint32; 
+            description
+                "For OFPXMT_OFB_IPV6_EXTHDR";
+        }
+
+    }
+
+    grouping ofp_oxm_experimenter_field {
+        description
+            "Header for OXM experimenter match fields.
+ The experimenter class should not use OXM_HEADER() macros for defining
+ fields due to this extra header.";
+        leaf oxm_header {
+            type  uint32; 
+            description
+                "oxm_class = OFPXMC_EXPERIMENTER";
+        }
+
+        leaf experimenter {
+            type  uint32; 
+            description
+                "Experimenter ID which takes the same
+form as in struct ofp_experimenter_header.";
+        }
+
+    }
+
+    grouping ofp_action {
+        description
+            "Action header that is common to all actions.  The length includes the
+ header and any padding used to make the action 64-bit aligned.
+ NB: The length of an action  must  always be a multiple of eight.";
+        leaf type {
+            type  ofp_action_type;
+
+            description
+                "One of OFPAT_ .";
+        }
+
+        container output {
+            uses  ofp_action_output;
+
+            description
+                "";
+        }
+
+        container mpls_ttl {
+            uses  ofp_action_mpls_ttl;
+
+            description
+                "";
+        }
+
+        container push {
+            uses  ofp_action_push;
+
+            description
+                "";
+        }
+
+        container pop_mpls {
+            uses  ofp_action_pop_mpls;
+
+            description
+                "";
+        }
+
+        container group {
+            uses  ofp_action_group;
+
+            description
+                "";
+        }
+
+        container nw_ttl {
+            uses  ofp_action_nw_ttl;
+
+            description
+                "";
+        }
+
+        container set_field {
+            uses  ofp_action_set_field;
+
+            description
+                "";
+        }
+
+        container experimenter {
+            uses  ofp_action_experimenter;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping ofp_action_output {
+        description
+            "Action structure for OFPAT_OUTPUT, which sends packets out 'port'.
+ When the 'port' is the OFPP_CONTROLLER, 'max_len' indicates the max
+ number of bytes to send.  A 'max_len' of zero means no bytes of the
+ packet should be sent. A 'max_len' of OFPCML_NO_BUFFER means that
+ the packet is not buffered and the complete packet is to be sent to
+ the controller.";
+        leaf port {
+            type  uint32; 
+            description
+                "Output port.";
+        }
+
+        leaf max_len {
+            type  uint32; 
+            description
+                "Max length to send to controller.";
+        }
+
+    }
+
+    grouping ofp_action_mpls_ttl {
+        description
+            "Action structure for OFPAT_SET_MPLS_TTL.";
+        leaf mpls_ttl {
+            type  uint32; 
+            description
+                "MPLS TTL";
+        }
+
+    }
+
+    grouping ofp_action_push {
+        description
+            "Action structure for OFPAT_PUSH_VLAN MPLS PBB.";
+        leaf ethertype {
+            type  uint32; 
+            description
+                "Ethertype";
+        }
+
+    }
+
+    grouping ofp_action_pop_mpls {
+        description
+            "Action structure for OFPAT_POP_MPLS.";
+        leaf ethertype {
+            type  uint32; 
+            description
+                "Ethertype";
+        }
+
+    }
+
+    grouping ofp_action_group {
+        description
+            "Action structure for OFPAT_GROUP.";
+        leaf group_id {
+            type  uint32; 
+            description
+                "Group identifier.";
+        }
+
+    }
+
+    grouping ofp_action_nw_ttl {
+        description
+            "Action structure for OFPAT_SET_NW_TTL.";
+        leaf nw_ttl {
+            type  uint32; 
+            description
+                "IP TTL";
+        }
+
+    }
+
+    grouping ofp_action_set_field {
+        description
+            "Action structure for OFPAT_SET_FIELD.";
+        container field {
+            uses  ofp_oxm_field;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping ofp_action_experimenter {
+        description
+            "Action header for OFPAT_EXPERIMENTER.
+ The rest of the body is experimenter-defined.";
+        leaf experimenter {
+            type  uint32; 
+            description
+                "Experimenter ID which takes the same
+form as in struct
+ofp_experimenter_header.";
+        }
+
+        leaf data {
+            type  binary; 
+            description
+                "";
+        }
+
+    }
+
+    grouping ofp_instruction {
+        description
+            "Instruction header that is common to all instructions.  The length includes
+ the header and any padding used to make the instruction 64-bit aligned.
+ NB: The length of an instruction  must  always be a multiple of eight.";
+        leaf type {
+            type  uint32; 
+            description
+                "Instruction type";
+        }
+
+        container goto_table {
+            uses  ofp_instruction_goto_table;
+
+            description
+                "";
+        }
+
+        container write_metadata {
+            uses  ofp_instruction_write_metadata;
+
+            description
+                "";
+        }
+
+        container actions {
+            uses  ofp_instruction_actions;
+
+            description
+                "";
+        }
+
+        container meter {
+            uses  ofp_instruction_meter;
+
+            description
+                "";
+        }
+
+        container experimenter {
+            uses  ofp_instruction_experimenter;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping ofp_instruction_goto_table {
+        description
+            "Instruction structure for OFPIT_GOTO_TABLE";
+        leaf table_id {
+            type  uint32; 
+            description
+                "Set next table in the lookup pipeline";
+        }
+
+    }
+
+    grouping ofp_instruction_write_metadata {
+        description
+            "Instruction structure for OFPIT_WRITE_METADATA";
+        leaf metadata {
+            type  uint64; 
+            description
+                "Metadata value to write";
+        }
+
+        leaf metadata_mask {
+            type  uint64; 
+            description
+                "Metadata write bitmask";
+        }
+
+    }
+
+    grouping ofp_instruction_actions {
+        description
+            "Instruction structure for OFPIT_WRITE APPLY CLEAR_ACTIONS";
+        list actions {
+            key "type";
+            uses  ofp_action;
+
+            description
+                "0 or more actions associated
+with OFPIT_WRITE_ACTIONS and
+OFPIT_APPLY_ACTIONS";
+        }
+
+    }
+
+    grouping ofp_instruction_meter {
+        description
+            "Instruction structure for OFPIT_METER";
+        leaf meter_id {
+            type  uint32; 
+            description
+                "Meter instance.";
+        }
+
+    }
+
+    grouping ofp_instruction_experimenter {
+        description
+            "Instruction structure for experimental instructions";
+        leaf experimenter {
+            type  uint32; 
+            description
+                "Experimenter ID which takes the same form
+as in struct ofp_experimenter_header.";
+        }
+
+        leaf data {
+            type  binary; 
+            description
+                "Experimenter-defined arbitrary additional data.";
+        }
+
+    }
+
+    grouping ofp_flow_mod {
+        description
+            "Flow setup and teardown (controller -> datapath).";
+        leaf cookie {
+            type  uint64; 
+            description
+                "ofp_header header;
+Opaque controller-issued identifier.";
+        }
+
+        leaf cookie_mask {
+            type  uint64; 
+            description
+                "Mask used to restrict the cookie bits
+that must match when the command is
+OFPFC_MODIFY  or OFPFC_DELETE . A value
+of 0 indicates no restriction.";
+        }
+
+        leaf table_id {
+            type  uint32; 
+            description
+                "ID of the table to put the flow in.
+For OFPFC_DELETE_  commands, OFPTT_ALL
+can also be used to delete matching
+flows from all tables.";
+        }
+
+        leaf command {
+            type  ofp_flow_mod_command;
+
+            description
+                "One of OFPFC_ .";
+        }
+
+        leaf idle_timeout {
+            type  uint32; 
+            description
+                "Idle time before discarding (seconds).";
+        }
+
+        leaf hard_timeout {
+            type  uint32; 
+            description
+                "Max time before discarding (seconds).";
+        }
+
+        leaf priority {
+            type  uint32; 
+            description
+                "Priority level of flow entry.";
+        }
+
+        leaf buffer_id {
+            type  uint32; 
+            description
+                "Buffered packet to apply to, or
+OFP_NO_BUFFER.
+Not meaningful for OFPFC_DELETE .";
+        }
+
+        leaf out_port {
+            type  uint32; 
+            description
+                "For OFPFC_DELETE  commands, require
+matching entries to include this as an
+output port.  A value of OFPP_ANY
+indicates no restriction.";
+        }
+
+        leaf out_group {
+            type  uint32; 
+            description
+                "For OFPFC_DELETE  commands, require
+matching entries to include this as an
+output group.  A value of OFPG_ANY
+indicates no restriction.";
+        }
+
+        leaf flags {
+            type  uint32; 
+            description
+                "Bitmap of OFPFF_  flags.";
+        }
+
+        container match {
+            uses  ofp_match;
+
+            description
+                "Fields to match. Variable size.";
+        }
+
+        list instructions {
+            key "type";
+            uses  ofp_instruction;
+
+            description
+                "0 or more.";
+        }
+
+    }
+
+    grouping ofp_bucket {
+        description
+            "Bucket for use in groups.";
+        leaf weight {
+            type  uint32; 
+            description
+                "Relative weight of bucket.  Only
+defined for select groups.";
+        }
+
+        leaf watch_port {
+            type  uint32; 
+            description
+                "Port whose state affects whether this
+bucket is live.  Only required for fast
+failover groups.";
+        }
+
+        leaf watch_group {
+            type  uint32; 
+            description
+                "Group whose state affects whether this
+bucket is live.  Only required for fast
+failover groups.";
+        }
+
+        list actions {
+            key "type";
+            uses  ofp_action;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping ofp_group_mod {
+        description
+            "Group setup and teardown (controller -> datapath).";
+        leaf command {
+            type  ofp_group_mod_command;
+
+            description
+                "ofp_header header;
+One of OFPGC_ .";
+        }
+
+        leaf type {
+            type  ofp_group_type;
+
+            description
+                "One of OFPGT_ .";
+        }
+
+        leaf group_id {
+            type  uint32; 
+            description
+                "Group identifier.";
+        }
+
+        list buckets {
+            key "weight";
+            uses  ofp_bucket;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping ofp_packet_out {
+        description
+            "Send packet (controller -> datapath).Special buffer-id to indicate 'no buffer'#define OFP_NO_BUFFER 0xffffffff";
+        leaf buffer_id {
+            type  uint32; 
+            description
+                "ofp_header header;
+ID assigned by datapath (OFP_NO_BUFFER
+if none).";
+        }
+
+        leaf in_port {
+            type  uint32; 
+            description
+                "Packet's input port or OFPP_CONTROLLER.";
+        }
+
+        list actions {
+            key "type";
+            uses  ofp_action;
+
+            description
+                "Action list - 0 or more.";
+        }
+
+        leaf data {
+            type  binary; 
+            description
+                "The variable size action list is optionally followed by packet data.
+ This data is only present and meaningful if buffer_id == -1.Packet data.";
+        }
+
+    }
+
+    grouping ofp_packet_in {
+        description
+            "Packet received on port (datapath -> controller).";
+        leaf buffer_id {
+            type  uint32; 
+            description
+                "ofp_header header;
+ID assigned by datapath.";
+        }
+
+        leaf reason {
+            type  ofp_packet_in_reason;
+
+            description
+                "Reason packet is being sent";
+        }
+
+        leaf table_id {
+            type  uint32; 
+            description
+                "ID of the table that was looked up";
+        }
+
+        leaf cookie {
+            type  uint64; 
+            description
+                "Cookie of the flow entry that was looked up.";
+        }
+
+        container match {
+            uses  ofp_match;
+
+            description
+                "Packet metadata. Variable size.";
+        }
+
+        leaf data {
+            type  binary; 
+            description
+                "Ethernet frame";
+        }
+
+    }
+
+    container ofp_flow_removed {
+        description
+            "Flow removed (datapath -> controller).";
+        leaf cookie {
+            type  uint64; 
+            description
+                "ofp_header header;
+Opaque controller-issued identifier.";
+        }
+
+        leaf priority {
+            type  uint32; 
+            description
+                "Priority level of flow entry.";
+        }
+
+        leaf reason {
+            type  ofp_flow_removed_reason;
+
+            description
+                "One of OFPRR_ .";
+        }
+
+        leaf table_id {
+            type  uint32; 
+            description
+                "ID of the table";
+        }
+
+        leaf duration_sec {
+            type  uint32; 
+            description
+                "Time flow was alive in seconds.";
+        }
+
+        leaf duration_nsec {
+            type  uint32; 
+            description
+                "Time flow was alive in nanoseconds beyond
+duration_sec.";
+        }
+
+        leaf idle_timeout {
+            type  uint32; 
+            description
+                "Idle timeout from original flow mod.";
+        }
+
+        leaf hard_timeout {
+            type  uint32; 
+            description
+                "Hard timeout from original flow mod.";
+        }
+
+        leaf packet_count {
+            type  uint64; 
+            description
+                "";
+        }
+
+        leaf byte_count {
+            type  uint64; 
+            description
+                "";
+        }
+
+        container match {
+            uses  ofp_match;
+
+            description
+                "Description of fields. Variable size.";
+        }
+
+    }
+
+    grouping ofp_meter_band_header {
+        description
+            "Common header for all meter bands";
+        leaf type {
+            type  ofp_meter_band_type;
+
+            description
+                "One of OFPMBT_ .";
+        }
+
+        leaf len {
+            type  uint32; 
+            description
+                "Length in bytes of this band.";
+        }
+
+        leaf rate {
+            type  uint32; 
+            description
+                "Rate for this band.";
+        }
+
+        leaf burst_size {
+            type  uint32; 
+            description
+                "Size of bursts.";
+        }
+
+    }
+
+    container ofp_meter_band_drop {
+        description
+            "OFPMBT_DROP band - drop packets";
+        leaf type {
+            type  uint32; 
+            description
+                "OFPMBT_DROP.";
+        }
+
+        leaf len {
+            type  uint32; 
+            description
+                "Length in bytes of this band.";
+        }
+
+        leaf rate {
+            type  uint32; 
+            description
+                "Rate for dropping packets.";
+        }
+
+        leaf burst_size {
+            type  uint32; 
+            description
+                "Size of bursts.";
+        }
+
+    }
+
+    container ofp_meter_band_dscp_remark {
+        description
+            "OFPMBT_DSCP_REMARK band - Remark DSCP in the IP header";
+        leaf type {
+            type  uint32; 
+            description
+                "OFPMBT_DSCP_REMARK.";
+        }
+
+        leaf len {
+            type  uint32; 
+            description
+                "Length in bytes of this band.";
+        }
+
+        leaf rate {
+            type  uint32; 
+            description
+                "Rate for remarking packets.";
+        }
+
+        leaf burst_size {
+            type  uint32; 
+            description
+                "Size of bursts.";
+        }
+
+        leaf prec_level {
+            type  uint32; 
+            description
+                "Number of drop precedence level to add.";
+        }
+
+    }
+
+    container ofp_meter_band_experimenter {
+        description
+            "OFPMBT_EXPERIMENTER band - Experimenter type.
+ The rest of the band is experimenter-defined.";
+        leaf type {
+            type  ofp_meter_band_type;
+
+            description
+                "One of OFPMBT_ .";
+        }
+
+        leaf len {
+            type  uint32; 
+            description
+                "Length in bytes of this band.";
+        }
+
+        leaf rate {
+            type  uint32; 
+            description
+                "Rate for this band.";
+        }
+
+        leaf burst_size {
+            type  uint32; 
+            description
+                "Size of bursts.";
+        }
+
+        leaf experimenter {
+            type  uint32; 
+            description
+                "Experimenter ID which takes the
+same form as in struct
+ofp_experimenter_header.";
+        }
+
+    }
+
+    container ofp_meter_mod {
+        description
+            "Meter configuration. OFPT_METER_MOD.";
+        leaf command {
+            type  ofp_meter_mod_command;
+
+            description
+                "ofp_header   header = 1;
+One of OFPMC_ .";
+        }
+
+        leaf flags {
+            type  uint32; 
+            description
+                "Bitmap of OFPMF_  flags.";
+        }
+
+        leaf meter_id {
+            type  uint32; 
+            description
+                "Meter instance.";
+        }
+
+        list bands {
+            key "type";
+            uses  ofp_meter_band_header;
+
+            description
+                "The band list length is
+inferred from the length field
+in the header.";
+        }
+
+    }
+
+    container ofp_error_msg {
+        description
+            "OFPT_ERROR: Error message (datapath -> controller).";
+        leaf type {
+            type  uint32; 
+            description
+                "ofp_header header;";
+        }
+
+        leaf code {
+            type  uint32; 
+            description
+                "";
+        }
+
+        leaf data {
+            type  binary; 
+            description
+                "Variable-length data.  Interpreted based
+on the type and code.  No padding.";
+        }
+
+    }
+
+    container ofp_error_experimenter_msg {
+        description
+            "OFPET_EXPERIMENTER: Error message (datapath -> controller).ofp_header header;";
+        leaf type {
+            type  uint32; 
+            description
+                "OFPET_EXPERIMENTER.";
+        }
+
+        leaf exp_type {
+            type  uint32; 
+            description
+                "Experimenter defined.";
+        }
+
+        leaf experimenter {
+            type  uint32; 
+            description
+                "Experimenter ID which takes the same form
+as in struct ofp_experimenter_header.";
+        }
+
+        leaf data {
+            type  binary; 
+            description
+                "Variable-length data.  Interpreted based
+on the type and code.  No padding.";
+        }
+
+    }
+
+    container ofp_multipart_request {
+        description
+            "";
+        leaf type {
+            type  ofp_multipart_type;
+
+            description
+                "ofp_header header;
+One of the OFPMP_  constants.";
+        }
+
+        leaf flags {
+            type  uint32; 
+            description
+                "OFPMPF_REQ_  flags.";
+        }
+
+        leaf body {
+            type  binary; 
+            description
+                "Body of the request. 0 or more bytes.";
+        }
+
+    }
+
+    container ofp_multipart_reply {
+        description
+            "";
+        leaf type {
+            type  ofp_multipart_type;
+
+            description
+                "ofp_header header;
+One of the OFPMP_  constants.";
+        }
+
+        leaf flags {
+            type  uint32; 
+            description
+                "OFPMPF_REPLY_  flags.";
+        }
+
+        leaf body {
+            type  binary; 
+            description
+                "Body of the reply. 0 or more bytes.";
+        }
+
+    }
+
+    grouping ofp_desc {
+        description
+            "Body of reply to OFPMP_DESC request.  Each entry is a NULL-terminated
+ ASCII string.#define DESC_STR_LEN   256
+#define SERIAL_NUM_LEN 32";
+        leaf mfr_desc {
+            type  string; 
+            description
+                "Manufacturer description.";
+        }
+
+        leaf hw_desc {
+            type  string; 
+            description
+                "Hardware description.";
+        }
+
+        leaf sw_desc {
+            type  string; 
+            description
+                "Software description.";
+        }
+
+        leaf serial_num {
+            type  string; 
+            description
+                "Serial number.";
+        }
+
+        leaf dp_desc {
+            type  string; 
+            description
+                "Human readable description of datapath.";
+        }
+
+    }
+
+    container ofp_flow_stats_request {
+        description
+            "Body for ofp_multipart_request of type OFPMP_FLOW.";
+        leaf table_id {
+            type  uint32; 
+            description
+                "ID of table to read (from ofp_table_stats),
+OFPTT_ALL for all tables.";
+        }
+
+        leaf out_port {
+            type  uint32; 
+            description
+                "Require matching entries to include this
+as an output port.  A value of OFPP_ANY
+indicates no restriction.";
+        }
+
+        leaf out_group {
+            type  uint32; 
+            description
+                "Require matching entries to include this
+as an output group.  A value of OFPG_ANY
+indicates no restriction.";
+        }
+
+        leaf cookie {
+            type  uint64; 
+            description
+                "Require matching entries to contain this
+cookie value";
+        }
+
+        leaf cookie_mask {
+            type  uint64; 
+            description
+                "Mask used to restrict the cookie bits that
+must match. A value of 0 indicates
+no restriction.";
+        }
+
+        container match {
+            uses  ofp_match;
+
+            description
+                "Fields to match. Variable size.";
+        }
+
+    }
+
+    grouping ofp_flow_stats {
+        description
+            "Body of reply to OFPMP_FLOW request.";
+        leaf id {
+            type  uint64; 
+            description
+                "Unique ID of flow within device.";
+        }
+
+        leaf table_id {
+            type  uint32; 
+            description
+                "ID of table flow came from.";
+        }
+
+        leaf duration_sec {
+            type  uint32; 
+            description
+                "Time flow has been alive in seconds.";
+        }
+
+        leaf duration_nsec {
+            type  uint32; 
+            description
+                "Time flow has been alive in nanoseconds
+beyond duration_sec.";
+        }
+
+        leaf priority {
+            type  uint32; 
+            description
+                "Priority of the entry.";
+        }
+
+        leaf idle_timeout {
+            type  uint32; 
+            description
+                "Number of seconds idle before expiration.";
+        }
+
+        leaf hard_timeout {
+            type  uint32; 
+            description
+                "Number of seconds before expiration.";
+        }
+
+        leaf flags {
+            type  uint32; 
+            description
+                "Bitmap of OFPFF_  flags.";
+        }
+
+        leaf cookie {
+            type  uint64; 
+            description
+                "Opaque controller-issued identifier.";
+        }
+
+        leaf packet_count {
+            type  uint64; 
+            description
+                "Number of packets in flow.";
+        }
+
+        leaf byte_count {
+            type  uint64; 
+            description
+                "Number of bytes in flow.";
+        }
+
+        container match {
+            uses  ofp_match;
+
+            description
+                "Description of fields. Variable size.";
+        }
+
+        list instructions {
+            key "type";
+            uses  ofp_instruction;
+
+            description
+                "Instruction set
+(0 or more)";
+        }
+
+    }
+
+    container ofp_aggregate_stats_request {
+        description
+            "Body for ofp_multipart_request of type OFPMP_AGGREGATE.";
+        leaf table_id {
+            type  uint32; 
+            description
+                "ID of table to read (from ofp_table_stats)
+OFPTT_ALL for all tables.";
+        }
+
+        leaf out_port {
+            type  uint32; 
+            description
+                "Require matching entries to include this
+as an output port.  A value of OFPP_ANY
+indicates no restriction.";
+        }
+
+        leaf out_group {
+            type  uint32; 
+            description
+                "Require matching entries to include this
+as an output group.  A value of OFPG_ANY
+indicates no restriction.";
+        }
+
+        leaf cookie {
+            type  uint64; 
+            description
+                "Require matching entries to contain this
+cookie value";
+        }
+
+        leaf cookie_mask {
+            type  uint64; 
+            description
+                "Mask used to restrict the cookie bits that
+must match. A value of 0 indicates
+no restriction.";
+        }
+
+        container match {
+            uses  ofp_match;
+
+            description
+                "Fields to match. Variable size.";
+        }
+
+    }
+
+    container ofp_aggregate_stats_reply {
+        description
+            "Body of reply to OFPMP_AGGREGATE request.";
+        leaf packet_count {
+            type  uint64; 
+            description
+                "Number of packets in flows.";
+        }
+
+        leaf byte_count {
+            type  uint64; 
+            description
+                "Number of bytes in flows.";
+        }
+
+        leaf flow_count {
+            type  uint32; 
+            description
+                "Number of flows.";
+        }
+
+    }
+
+    grouping ofp_table_feature_property {
+        description
+            "Common header for all Table Feature Properties";
+        leaf type {
+            type  ofp_table_feature_prop_type;
+
+            description
+                "One of OFPTFPT_ .";
+        }
+
+        container instructions {
+            uses  ofp_table_feature_prop_instructions;
+
+            description
+                "";
+        }
+
+        container next_tables {
+            uses  ofp_table_feature_prop_next_tables;
+
+            description
+                "";
+        }
+
+        container actions {
+            uses  ofp_table_feature_prop_actions;
+
+            description
+                "";
+        }
+
+        container oxm {
+            uses  ofp_table_feature_prop_oxm;
+
+            description
+                "";
+        }
+
+        container experimenter {
+            uses  ofp_table_feature_prop_experimenter;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping ofp_table_feature_prop_instructions {
+        description
+            "Instructions property";
+        list instructions {
+            key "type";
+            uses  ofp_instruction;
+
+            description
+                "One of OFPTFPT_INSTRUCTIONS,
+OFPTFPT_INSTRUCTIONS_MISS.List of instructions";
+        }
+
+    }
+
+    grouping ofp_table_feature_prop_next_tables {
+        description
+            "Next Tables property";
+        list next_table_ids {
+            key "next_table_ids";
+            leaf next_table_ids {
+                type  uint32; 
+                description
+                    "One of OFPTFPT_NEXT_TABLES,
+OFPTFPT_NEXT_TABLES_MISS.List of table ids.";
+            }
+            description
+                "One of OFPTFPT_NEXT_TABLES,
+OFPTFPT_NEXT_TABLES_MISS.List of table ids.";
+        }
+
+    }
+
+    grouping ofp_table_feature_prop_actions {
+        description
+            "Actions property";
+        list actions {
+            key "type";
+            uses  ofp_action;
+
+            description
+                "One of OFPTFPT_WRITE_ACTIONS,
+OFPTFPT_WRITE_ACTIONS_MISS,
+OFPTFPT_APPLY_ACTIONS,
+OFPTFPT_APPLY_ACTIONS_MISS.List of actions";
+        }
+
+    }
+
+    grouping ofp_table_feature_prop_oxm {
+        description
+            "Match, Wildcard or Set-Field propertyOne of OFPTFPT_MATCH,
+OFPTFPT_WILDCARDS,
+OFPTFPT_WRITE_SETFIELD,
+OFPTFPT_WRITE_SETFIELD_MISS,
+OFPTFPT_APPLY_SETFIELD,
+OFPTFPT_APPLY_SETFIELD_MISS.";
+        list oxm_ids {
+            key "oxm_ids";
+            leaf oxm_ids {
+                type  uint32; 
+                description
+                    "TODO is this a uint32???Array of OXM headers";
+            }
+            description
+                "TODO is this a uint32???Array of OXM headers";
+        }
+
+    }
+
+    grouping ofp_table_feature_prop_experimenter {
+        description
+            "Experimenter table feature property";
+        leaf experimenter {
+            type  uint32; 
+            description
+                "One of OFPTFPT_EXPERIMENTER,
+OFPTFPT_EXPERIMENTER_MISS.Experimenter ID which takes the same
+form as in struct
+ofp_experimenter_header.";
+        }
+
+        leaf exp_type {
+            type  uint32; 
+            description
+                "Experimenter defined.";
+        }
+
+        list experimenter_data {
+            key "experimenter_data";
+            leaf experimenter_data {
+                type  uint32; 
+                description
+                    "";
+            }
+            description
+                "";
+        }
+
+    }
+
+    container ofp_table_features {
+        description
+            "Body for ofp_multipart_request of type OFPMP_TABLE_FEATURES. 
+ Body of reply to OFPMP_TABLE_FEATURES request.";
+        leaf table_id {
+            type  uint32; 
+            description
+                "Identifier of table.  Lower numbered tables
+are consulted first.";
+        }
+
+        leaf name {
+            type  string; 
+            description
+                "";
+        }
+
+        leaf metadata_match {
+            type  uint64; 
+            description
+                "Bits of metadata table can match.";
+        }
+
+        leaf metadata_write {
+            type  uint64; 
+            description
+                "Bits of metadata table can write.";
+        }
+
+        leaf config {
+            type  uint32; 
+            description
+                "Bitmap of OFPTC_  values";
+        }
+
+        leaf max_entries {
+            type  uint32; 
+            description
+                "Max number of entries supported.";
+        }
+
+        list properties {
+            key "type";
+            uses  ofp_table_feature_property;
+
+            description
+                "Table Feature Property list";
+        }
+
+    }
+
+    container ofp_table_stats {
+        description
+            "Body of reply to OFPMP_TABLE request.";
+        leaf table_id {
+            type  uint32; 
+            description
+                "Identifier of table.  Lower numbered tables
+are consulted first.";
+        }
+
+        leaf active_count {
+            type  uint32; 
+            description
+                "Number of active entries.";
+        }
+
+        leaf lookup_count {
+            type  uint64; 
+            description
+                "Number of packets looked up in table.";
+        }
+
+        leaf matched_count {
+            type  uint64; 
+            description
+                "Number of packets that hit table.";
+        }
+
+    }
+
+    container ofp_port_stats_request {
+        description
+            "Body for ofp_multipart_request of type OFPMP_PORT.";
+        leaf port_no {
+            type  uint32; 
+            description
+                "OFPMP_PORT message must request statistics
+ either for a single port (specified in
+ port_no) or for all ports (if port_no ==
+ OFPP_ANY).";
+        }
+
+    }
+
+    container ofp_port_stats {
+        description
+            "Body of reply to OFPMP_PORT request. If a counter is unsupported, set
+ the field to all ones.";
+        leaf port_no {
+            type  uint32; 
+            description
+                "";
+        }
+
+        leaf rx_packets {
+            type  uint64; 
+            description
+                "Number of received packets.";
+        }
+
+        leaf tx_packets {
+            type  uint64; 
+            description
+                "Number of transmitted packets.";
+        }
+
+        leaf rx_bytes {
+            type  uint64; 
+            description
+                "Number of received bytes.";
+        }
+
+        leaf tx_bytes {
+            type  uint64; 
+            description
+                "Number of transmitted bytes.";
+        }
+
+        leaf rx_dropped {
+            type  uint64; 
+            description
+                "Number of packets dropped by RX.";
+        }
+
+        leaf tx_dropped {
+            type  uint64; 
+            description
+                "Number of packets dropped by TX.";
+        }
+
+        leaf rx_errors {
+            type  uint64; 
+            description
+                "Number of receive errors.  This is a super-set
+of more specific receive errors and should be
+greater than or equal to the sum of all
+rx_ _err values.";
+        }
+
+        leaf tx_errors {
+            type  uint64; 
+            description
+                "Number of transmit errors.  This is a super-set
+of more specific transmit errors and should be
+greater than or equal to the sum of all
+tx_ _err values (none currently defined.)";
+        }
+
+        leaf rx_frame_err {
+            type  uint64; 
+            description
+                "Number of frame alignment errors.";
+        }
+
+        leaf rx_over_err {
+            type  uint64; 
+            description
+                "Number of packets with RX overrun.";
+        }
+
+        leaf rx_crc_err {
+            type  uint64; 
+            description
+                "Number of CRC errors.";
+        }
+
+        leaf collisions {
+            type  uint64; 
+            description
+                "Number of collisions.";
+        }
+
+        leaf duration_sec {
+            type  uint32; 
+            description
+                "Time port has been alive in seconds.";
+        }
+
+        leaf duration_nsec {
+            type  uint32; 
+            description
+                "Time port has been alive in nanoseconds
+beyond duration_sec.";
+        }
+
+    }
+
+    container ofp_group_stats_request {
+        description
+            "Body of OFPMP_GROUP request.";
+        leaf group_id {
+            type  uint32; 
+            description
+                "All groups if OFPG_ALL.";
+        }
+
+    }
+
+    grouping ofp_bucket_counter {
+        description
+            "Used in group stats replies.";
+        leaf packet_count {
+            type  uint64; 
+            description
+                "Number of packets processed by bucket.";
+        }
+
+        leaf byte_count {
+            type  uint64; 
+            description
+                "Number of bytes processed by bucket.";
+        }
+
+    }
+
+    grouping ofp_group_stats {
+        description
+            "Body of reply to OFPMP_GROUP request.";
+        leaf group_id {
+            type  uint32; 
+            description
+                "Group identifier.";
+        }
+
+        leaf ref_count {
+            type  uint32; 
+            description
+                "Number of flows or groups that directly
+forward to this group.";
+        }
+
+        leaf packet_count {
+            type  uint64; 
+            description
+                "Number of packets processed by group.";
+        }
+
+        leaf byte_count {
+            type  uint64; 
+            description
+                "Number of bytes processed by group.";
+        }
+
+        leaf duration_sec {
+            type  uint32; 
+            description
+                "Time group has been alive in seconds.";
+        }
+
+        leaf duration_nsec {
+            type  uint32; 
+            description
+                "Time group has been alive in nanoseconds
+beyond duration_sec.";
+        }
+
+        list bucket_stats {
+            key "packet_count";
+            uses  ofp_bucket_counter;
+
+            description
+                "One counter set per
+bucket.";
+        }
+
+    }
+
+    container ofp_group_desc {
+        description
+            "Body of reply to OFPMP_GROUP_DESC request.";
+        leaf type {
+            type  ofp_group_type;
+
+            description
+                "One of OFPGT_ .";
+        }
+
+        leaf group_id {
+            type  uint32; 
+            description
+                "Group identifier.";
+        }
+
+        list buckets {
+            key "weight";
+            uses  ofp_bucket;
+
+            description
+                "List of buckets - 0 or more.";
+        }
+
+    }
+
+    grouping ofp_group_entry {
+        description
+            "";
+        leaf type {
+            type  ofp_group_type;
+
+            description
+                "One of OFPGT_ .";
+        }
+
+        leaf group_id {
+            type  uint32; 
+            description
+                "Group identifier.";
+        }
+
+        list buckets {
+            key "weight";
+            uses  ofp_bucket;
+
+            description
+                "List of buckets - 0 or more.";
+        }
+
+        container stats {
+            uses  ofp_group_stats;
+
+            description
+                "ofp_group_desc desc = 1;";
+        }
+
+    }
+
+    container ofp_group_features {
+        description
+            "Body of reply to OFPMP_GROUP_FEATURES request. Group features.";
+        leaf types {
+            type  uint32; 
+            description
+                "Bitmap of (1 << OFPGT_ ) values supported.";
+        }
+
+        leaf capabilities {
+            type  uint32; 
+            description
+                "Bitmap of OFPGFC_  capability supported.";
+        }
+
+        list max_groups {
+            key "max_groups";
+            leaf max_groups {
+                type  uint32; 
+                description
+                    "Maximum number of groups for each type.";
+            }
+            description
+                "Maximum number of groups for each type.";
+        }
+
+        list actions {
+            key "actions";
+            leaf actions {
+                type  uint32; 
+                description
+                    "Bitmaps of (1 << OFPAT_ ) values
+supported.";
+            }
+            description
+                "Bitmaps of (1 << OFPAT_ ) values
+supported.";
+        }
+
+    }
+
+    container ofp_meter_multipart_request {
+        description
+            "Body of OFPMP_METER and OFPMP_METER_CONFIG requests.";
+        leaf meter_id {
+            type  uint32; 
+            description
+                "Meter instance, or OFPM_ALL.";
+        }
+
+    }
+
+    grouping ofp_meter_band_stats {
+        description
+            "Statistics for each meter band";
+        leaf packet_band_count {
+            type  uint64; 
+            description
+                "Number of packets in band.";
+        }
+
+        leaf byte_band_count {
+            type  uint64; 
+            description
+                "Number of bytes in band.";
+        }
+
+    }
+
+    container ofp_meter_stats {
+        description
+            "Body of reply to OFPMP_METER request. Meter statistics.";
+        leaf meter_id {
+            type  uint32; 
+            description
+                "Meter instance.";
+        }
+
+        leaf flow_count {
+            type  uint32; 
+            description
+                "Number of flows bound to meter.";
+        }
+
+        leaf packet_in_count {
+            type  uint64; 
+            description
+                "Number of packets in input.";
+        }
+
+        leaf byte_in_count {
+            type  uint64; 
+            description
+                "Number of bytes in input.";
+        }
+
+        leaf duration_sec {
+            type  uint32; 
+            description
+                "Time meter has been alive in seconds.";
+        }
+
+        leaf duration_nsec {
+            type  uint32; 
+            description
+                "Time meter has been alive in nanoseconds
+beyond duration_sec.";
+        }
+
+        list band_stats {
+            key "packet_band_count";
+            uses  ofp_meter_band_stats;
+
+            description
+                "The band_stats length is
+inferred from the length field.";
+        }
+
+    }
+
+    container ofp_meter_config {
+        description
+            "Body of reply to OFPMP_METER_CONFIG request. Meter configuration.";
+        leaf flags {
+            type  uint32; 
+            description
+                "All OFPMF_  that apply.";
+        }
+
+        leaf meter_id {
+            type  uint32; 
+            description
+                "Meter instance.";
+        }
+
+        list bands {
+            key "type";
+            uses  ofp_meter_band_header;
+
+            description
+                "The bands length is
+inferred from the length field.";
+        }
+
+    }
+
+    container ofp_meter_features {
+        description
+            "Body of reply to OFPMP_METER_FEATURES request. Meter features.";
+        leaf max_meter {
+            type  uint32; 
+            description
+                "Maximum number of meters.";
+        }
+
+        leaf band_types {
+            type  uint32; 
+            description
+                "Bitmaps of (1 << OFPMBT_ ) values supported.";
+        }
+
+        leaf capabilities {
+            type  uint32; 
+            description
+                "Bitmaps of  ofp_meter_flags .";
+        }
+
+        leaf max_bands {
+            type  uint32; 
+            description
+                "Maximum bands per meters";
+        }
+
+        leaf max_color {
+            type  uint32; 
+            description
+                "Maximum color value";
+        }
+
+    }
+
+    container ofp_experimenter_multipart_header {
+        description
+            "Body for ofp_multipart_request reply of type OFPMP_EXPERIMENTER.";
+        leaf experimenter {
+            type  uint32; 
+            description
+                "Experimenter ID which takes the same form
+as in struct ofp_experimenter_header.";
+        }
+
+        leaf exp_type {
+            type  uint32; 
+            description
+                "Experimenter defined.";
+        }
+
+        leaf data {
+            type  binary; 
+            description
+                "Experimenter-defined arbitrary additional data.";
+        }
+
+    }
+
+    container ofp_experimenter_header {
+        description
+            "Experimenter extension.";
+        leaf experimenter {
+            type  uint32; 
+            description
+                "ofp_header header;     Type OFPT_EXPERIMENTER.   
+Experimenter ID:
+ - MSB 0: low-order bytes are IEEE OUI.
+ - MSB != 0: defined by ONF.";
+        }
+
+        leaf exp_type {
+            type  uint32; 
+            description
+                "Experimenter defined.";
+        }
+
+        leaf data {
+            type  binary; 
+            description
+                "Experimenter-defined arbitrary additional data.";
+        }
+
+    }
+
+    grouping ofp_queue_prop_header {
+        description
+            "Common description for a queue.";
+        leaf property {
+            type  uint32; 
+            description
+                "One of OFPQT_.";
+        }
+
+        leaf len {
+            type  uint32; 
+            description
+                "Length of property, including this header.";
+        }
+
+    }
+
+    container ofp_queue_prop_min_rate {
+        description
+            "Min-Rate queue property description.";
+        container prop_header {
+            uses  ofp_queue_prop_header;
+
+            description
+                "prop: OFPQT_MIN, len: 16.";
+        }
+
+        leaf rate {
+            type  uint32; 
+            description
+                "In 1 10 of a percent = 0;>1000 -> disabled.";
+        }
+
+    }
+
+    container ofp_queue_prop_max_rate {
+        description
+            "Max-Rate queue property description.";
+        container prop_header {
+            uses  ofp_queue_prop_header;
+
+            description
+                "prop: OFPQT_MAX, len: 16.";
+        }
+
+        leaf rate {
+            type  uint32; 
+            description
+                "In 1 10 of a percent = 0;>1000 -> disabled.";
+        }
+
+    }
+
+    container ofp_queue_prop_experimenter {
+        description
+            "Experimenter queue property description.";
+        container prop_header {
+            uses  ofp_queue_prop_header;
+
+            description
+                "prop: OFPQT_EXPERIMENTER";
+        }
+
+        leaf experimenter {
+            type  uint32; 
+            description
+                "Experimenter ID which takes the same
+form as in struct
+ofp_experimenter_header.";
+        }
+
+        leaf data {
+            type  binary; 
+            description
+                "Experimenter defined data.";
+        }
+
+    }
+
+    grouping ofp_packet_queue {
+        description
+            "Full description for a queue.";
+        leaf queue_id {
+            type  uint32; 
+            description
+                "id for the specific queue.";
+        }
+
+        leaf port {
+            type  uint32; 
+            description
+                "Port this queue is attached to.";
+        }
+
+        list properties {
+            key "property";
+            uses  ofp_queue_prop_header;
+
+            description
+                "List of properties.";
+        }
+
+    }
+
+    container ofp_queue_get_config_request {
+        description
+            "Query for port queue configuration.";
+        leaf port {
+            type  uint32; 
+            description
+                "ofp_header header;
+Port to be queried. Should refer
+to a valid physical port (i.e. <= OFPP_MAX),
+or OFPP_ANY to request all configured
+queues.";
+        }
+
+    }
+
+    container ofp_queue_get_config_reply {
+        description
+            "Queue configuration for a given port.";
+        leaf port {
+            type  uint32; 
+            description
+                "ofp_header header;";
+        }
+
+        list queues {
+            key "queue_id";
+            uses  ofp_packet_queue;
+
+            description
+                "List of configured queues.";
+        }
+
+    }
+
+    container ofp_action_set_queue {
+        description
+            "OFPAT_SET_QUEUE action struct: send packets to given queue on port.";
+        leaf type {
+            type  uint32; 
+            description
+                "OFPAT_SET_QUEUE.";
+        }
+
+        leaf queue_id {
+            type  uint32; 
+            description
+                "Queue id for the packets.";
+        }
+
+    }
+
+    container ofp_queue_stats_request {
+        description
+            "";
+        leaf port_no {
+            type  uint32; 
+            description
+                "All ports if OFPP_ANY.";
+        }
+
+        leaf queue_id {
+            type  uint32; 
+            description
+                "All queues if OFPQ_ALL.";
+        }
+
+    }
+
+    container ofp_queue_stats {
+        description
+            "";
+        leaf port_no {
+            type  uint32; 
+            description
+                "";
+        }
+
+        leaf queue_id {
+            type  uint32; 
+            description
+                "Queue i.d";
+        }
+
+        leaf tx_bytes {
+            type  uint64; 
+            description
+                "Number of transmitted bytes.";
+        }
+
+        leaf tx_packets {
+            type  uint64; 
+            description
+                "Number of transmitted packets.";
+        }
+
+        leaf tx_errors {
+            type  uint64; 
+            description
+                "Number of packets dropped due to overrun.";
+        }
+
+        leaf duration_sec {
+            type  uint32; 
+            description
+                "Time queue has been alive in seconds.";
+        }
+
+        leaf duration_nsec {
+            type  uint32; 
+            description
+                "Time queue has been alive in nanoseconds
+beyond duration_sec.";
+        }
+
+    }
+
+    container ofp_role_request {
+        description
+            "Role request and reply message.";
+        leaf role {
+            type  ofp_controller_role;
+
+            description
+                "ofp_header header;           Type OFPT_ROLE_REQUEST OFPT_ROLE_REPLY.   
+One of OFPCR_ROLE_ .";
+        }
+
+        leaf generation_id {
+            type  uint64; 
+            description
+                "Master Election Generation Id";
+        }
+
+    }
+
+    container ofp_async_config {
+        description
+            "Asynchronous message configuration.";
+        list packet_in_mask {
+            key "packet_in_mask";
+            leaf packet_in_mask {
+                type  uint32; 
+                description
+                    "ofp_header header;       OFPT_GET_ASYNC_REPLY or OFPT_SET_ASYNC.   
+Bitmasks of OFPR_  values.";
+            }
+            description
+                "ofp_header header;       OFPT_GET_ASYNC_REPLY or OFPT_SET_ASYNC.   
+Bitmasks of OFPR_  values.";
+        }
+
+        list port_status_mask {
+            key "port_status_mask";
+            leaf port_status_mask {
+                type  uint32; 
+                description
+                    "Bitmasks of OFPPR_  values.";
+            }
+            description
+                "Bitmasks of OFPPR_  values.";
+        }
+
+        list flow_removed_mask {
+            key "flow_removed_mask";
+            leaf flow_removed_mask {
+                type  uint32; 
+                description
+                    "Bitmasks of OFPRR_  values.";
+            }
+            description
+                "Bitmasks of OFPRR_  values.";
+        }
+
+    }
+
+    grouping FlowTableUpdate {
+        description
+            "ADDITIONAL VOLTHA SPECIFIC MESSAGE TYPES, AIDING RPC CALLS";
+        leaf id {
+            type  string; 
+            description
+                "Device.id or LogicalDevice.id";
+        }
+
+        container flow_mod {
+            uses  ofp_flow_mod;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping FlowGroupTableUpdate {
+        description
+            "";
+        leaf id {
+            type  string; 
+            description
+                "Device.id or LogicalDevice.id";
+        }
+
+        container group_mod {
+            uses  ofp_group_mod;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping Flows {
+        description
+            "";
+        list items {
+            key "id";
+            uses  ofp_flow_stats;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping FlowGroups {
+        description
+            "";
+        list items {
+            key "type";
+            uses  ofp_group_entry;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping PacketIn {
+        description
+            "";
+        leaf id {
+            type  string; 
+            description
+                "LogicalDevice.id";
+        }
+
+        container packet_in {
+            uses  ofp_packet_in;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping PacketOut {
+        description
+            "";
+        leaf id {
+            type  string; 
+            description
+                "LogicalDevice.id";
+        }
+
+        container packet_out {
+            uses  ofp_packet_out;
+
+            description
+                "";
+        }
+
+    }
+
+}
\ No newline at end of file
diff --git a/experiments/netconf/proto2yang/ietf-voltha.yang b/experiments/netconf/proto2yang/ietf-voltha.yang
new file mode 100644
index 0000000..b79eef1
--- /dev/null
+++ b/experiments/netconf/proto2yang/ietf-voltha.yang
@@ -0,0 +1,798 @@
+
+module ietf-voltha {
+
+
+    namespace "urn:opencord:params:xml:ns:voltha:ietf-voltha";
+    prefix voltha;
+
+    import ietf-openflow_13 { prefix openflow_13 ; }
+    import ietf-adapter { prefix adapter ; }
+    import ietf-health { prefix health ; }
+    import ietf-common { prefix common ; }
+    import ietf-device { prefix device ; }
+    import ietf-logical_device { prefix logical_device ; }
+    import ietf-empty { prefix empty ; }
+
+    organization "CORD";
+    contact
+        " Any name";
+
+    description
+        "";
+
+    revision "2016-11-15" {
+        description "Initial revision.";
+        reference "reference";
+    }
+
+
+    grouping DeviceGroup {
+        description
+            "";
+        leaf id {
+            type  string; 
+            description
+                "";
+        }
+
+        list logical_devices {
+            key "id";
+            uses  logical_device:LogicalDevice;
+
+            description
+                "";
+        }
+
+        list devices {
+            key "id";
+            uses  device:Device;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping DeviceGroups {
+        description
+            "";
+        list items {
+            key "id";
+            uses  DeviceGroup;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping VolthaInstance {
+        description
+            "Top-level (root) node for a Voltha Instance";
+        leaf instance_id {
+            type  string; 
+            description
+                "";
+        }
+
+        leaf version {
+            type  string; 
+            description
+                "";
+        }
+
+        leaf log_level {
+            type  common:LogLevel;
+
+            description
+                "";
+        }
+
+        container health {
+            uses  health:HealthStatus;
+
+            description
+                "";
+        }
+
+        list adapters {
+            key "id";
+            uses  adapter:Adapter;
+
+            description
+                "";
+        }
+
+        list logical_devices {
+            key "id";
+            uses  logical_device:LogicalDevice;
+
+            description
+                "";
+        }
+
+        list devices {
+            key "id";
+            uses  device:Device;
+
+            description
+                "";
+        }
+
+        list device_types {
+            key "id";
+            uses  device:DeviceType;
+
+            description
+                "";
+        }
+
+        list device_groups {
+            key "id";
+            uses  DeviceGroup;
+
+            description
+                "";
+        }
+
+    }
+
+    grouping VolthaInstances {
+        description
+            "";
+        list items {
+            key "items";
+            leaf items {
+                type  string; 
+                description
+                    "";
+            }
+            description
+                "";
+        }
+
+    }
+
+    grouping Voltha {
+        description
+            "Voltha representing the entire Voltha cluster";
+        leaf version {
+            type  string; 
+            description
+                "";
+        }
+
+        leaf log_level {
+            type  common:LogLevel;
+
+            description
+                "";
+        }
+
+        list instances {
+            key "instance_id";
+            uses  VolthaInstance;
+
+            description
+                "";
+        }
+
+        list adapters {
+            key "id";
+            uses  adapter:Adapter;
+
+            description
+                "";
+        }
+
+        list logical_devices {
+            key "id";
+            uses  logical_device:LogicalDevice;
+
+            description
+                "";
+        }
+
+        list devices {
+            key "id";
+            uses  device:Device;
+
+            description
+                "";
+        }
+
+        list device_groups {
+            key "id";
+            uses  DeviceGroup;
+
+            description
+                "";
+        }
+
+    }
+
+    /*  Cluster-wide Voltha APIs
+
+ These APIs are potentially dispatched to the leader of the Voltha cluster,
+ to a specific Voltha instance which owns the given device or logical device." */
+    rpc VolthaGlobalService-GetVoltha {
+        description
+            "Get high level information on the Voltha cluster";
+        input {
+            uses  empty:Empty;
+
+        }
+        output {
+            uses  Voltha;
+
+        }
+    }
+
+    rpc VolthaGlobalService-ListVolthaInstances {
+        description
+            "List all Voltha cluster instances";
+        input {
+            uses  empty:Empty;
+
+        }
+        output {
+            uses  VolthaInstances;
+
+        }
+    }
+
+    rpc VolthaGlobalService-GetVolthaInstance {
+        description
+            "Get details on a Voltha cluster instance";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  VolthaInstance;
+
+        }
+    }
+
+    rpc VolthaGlobalService-ListLogicalDevices {
+        description
+            "List all logical devices managed by the Voltha cluster";
+        input {
+            uses  empty:Empty;
+
+        }
+        output {
+            uses  logical_device:LogicalDevices;
+
+        }
+    }
+
+    rpc VolthaGlobalService-GetLogicalDevice {
+        description
+            "Get additional information on a given logical device";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  logical_device:LogicalDevice;
+
+        }
+    }
+
+    rpc VolthaGlobalService-ListLogicalDevicePorts {
+        description
+            "List ports of a logical device";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  logical_device:LogicalPorts;
+
+        }
+    }
+
+    rpc VolthaGlobalService-ListLogicalDeviceFlows {
+        description
+            "List all flows of a logical device";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  openflow_13:Flows;
+
+        }
+    }
+
+    rpc VolthaGlobalService-UpdateLogicalDeviceFlowTable {
+        description
+            "Update flow table for logical device";
+        input {
+            uses  openflow_13:FlowTableUpdate;
+
+        }
+        output {
+            uses  empty:Empty;
+
+        }
+    }
+
+    rpc VolthaGlobalService-ListLogicalDeviceFlowGroups {
+        description
+            "List all flow groups of a logical device";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  openflow_13:FlowGroups;
+
+        }
+    }
+
+    rpc VolthaGlobalService-UpdateLogicalDeviceFlowGroupTable {
+        description
+            "Update group table for device";
+        input {
+            uses  openflow_13:FlowGroupTableUpdate;
+
+        }
+        output {
+            uses  empty:Empty;
+
+        }
+    }
+
+    rpc VolthaGlobalService-ListDevices {
+        description
+            "List all physical devices controlled by the Voltha cluster";
+        input {
+            uses  empty:Empty;
+
+        }
+        output {
+            uses  device:Devices;
+
+        }
+    }
+
+    rpc VolthaGlobalService-GetDevice {
+        description
+            "Get more information on a given physical device";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  device:Device;
+
+        }
+    }
+
+    rpc VolthaGlobalService-CreateDevice {
+        description
+            "Pre-provision a new physical device";
+        input {
+            uses  device:Device;
+
+        }
+        output {
+            uses  device:Device;
+
+        }
+    }
+
+    rpc VolthaGlobalService-ActivateDevice {
+        description
+            "Activate a pre-provisioned device";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  empty:Empty;
+
+        }
+    }
+
+    rpc VolthaGlobalService-ListDevicePorts {
+        description
+            "List ports of a device";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  device:Ports;
+
+        }
+    }
+
+    rpc VolthaGlobalService-ListDeviceFlows {
+        description
+            "List all flows of a device";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  openflow_13:Flows;
+
+        }
+    }
+
+    rpc VolthaGlobalService-ListDeviceFlowGroups {
+        description
+            "List all flow groups of a device";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  openflow_13:FlowGroups;
+
+        }
+    }
+
+    rpc VolthaGlobalService-ListDeviceTypes {
+        description
+            "List device types known to Voltha";
+        input {
+            uses  empty:Empty;
+
+        }
+        output {
+            uses  device:DeviceTypes;
+
+        }
+    }
+
+    rpc VolthaGlobalService-GetDeviceType {
+        description
+            "Get additional information on a device type";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  device:DeviceType;
+
+        }
+    }
+
+    rpc VolthaGlobalService-ListDeviceGroups {
+        description
+            "List all device sharding groups";
+        input {
+            uses  empty:Empty;
+
+        }
+        output {
+            uses  DeviceGroups;
+
+        }
+    }
+
+    rpc VolthaGlobalService-GetDeviceGroup {
+        description
+            "Get additional information on a device group";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  DeviceGroup;
+
+        }
+    }
+
+
+    /*  Per-instance APIs
+
+ These APIs are always served locally by the Voltha instance on which the
+ call is made." */
+    rpc VolthaLocalService-GetVolthaInstance {
+        description
+            "Get information on this Voltha instance";
+        input {
+            uses  empty:Empty;
+
+        }
+        output {
+            uses  VolthaInstance;
+
+        }
+    }
+
+    rpc VolthaLocalService-GetHealth {
+        description
+            "Get the health state of the Voltha instance";
+        input {
+            uses  empty:Empty;
+
+        }
+        output {
+            uses  health:HealthStatus;
+
+        }
+    }
+
+    rpc VolthaLocalService-ListAdapters {
+        description
+            "List all active adapters (plugins) in this Voltha instance";
+        input {
+            uses  empty:Empty;
+
+        }
+        output {
+            uses  adapter:Adapters;
+
+        }
+    }
+
+    rpc VolthaLocalService-ListLogicalDevices {
+        description
+            "List all logical devices managed by this Voltha instance";
+        input {
+            uses  empty:Empty;
+
+        }
+        output {
+            uses  logical_device:LogicalDevices;
+
+        }
+    }
+
+    rpc VolthaLocalService-GetLogicalDevice {
+        description
+            "Get additional information on given logical device";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  logical_device:LogicalDevice;
+
+        }
+    }
+
+    rpc VolthaLocalService-ListLogicalDevicePorts {
+        description
+            "List ports of a logical device";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  logical_device:LogicalPorts;
+
+        }
+    }
+
+    rpc VolthaLocalService-ListLogicalDeviceFlows {
+        description
+            "List all flows of a logical device";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  openflow_13:Flows;
+
+        }
+    }
+
+    rpc VolthaLocalService-UpdateLogicalDeviceFlowTable {
+        description
+            "Update flow table for logical device";
+        input {
+            uses  openflow_13:FlowTableUpdate;
+
+        }
+        output {
+            uses  empty:Empty;
+
+        }
+    }
+
+    rpc VolthaLocalService-ListLogicalDeviceFlowGroups {
+        description
+            "List all flow groups of a logical device";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  openflow_13:FlowGroups;
+
+        }
+    }
+
+    rpc VolthaLocalService-UpdateLogicalDeviceFlowGroupTable {
+        description
+            "Update group table for logical device";
+        input {
+            uses  openflow_13:FlowGroupTableUpdate;
+
+        }
+        output {
+            uses  empty:Empty;
+
+        }
+    }
+
+    rpc VolthaLocalService-ListDevices {
+        description
+            "List all physical devices managed by this Voltha instance";
+        input {
+            uses  empty:Empty;
+
+        }
+        output {
+            uses  device:Devices;
+
+        }
+    }
+
+    rpc VolthaLocalService-GetDevice {
+        description
+            "Get additional information on this device";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  device:Device;
+
+        }
+    }
+
+    rpc VolthaLocalService-CreateDevice {
+        description
+            "Pre-provision a new physical device";
+        input {
+            uses  device:Device;
+
+        }
+        output {
+            uses  device:Device;
+
+        }
+    }
+
+    rpc VolthaLocalService-ActivateDevice {
+        description
+            "Activate a pre-provisioned device";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  empty:Empty;
+
+        }
+    }
+
+    rpc VolthaLocalService-ListDevicePorts {
+        description
+            "List ports of a device";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  device:Ports;
+
+        }
+    }
+
+    rpc VolthaLocalService-ListDeviceFlows {
+        description
+            "List all flows of a device";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  openflow_13:Flows;
+
+        }
+    }
+
+    rpc VolthaLocalService-ListDeviceFlowGroups {
+        description
+            "List all flow groups of a device";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  openflow_13:FlowGroups;
+
+        }
+    }
+
+    rpc VolthaLocalService-ListDeviceTypes {
+        description
+            "List device types know to Voltha instance";
+        input {
+            uses  empty:Empty;
+
+        }
+        output {
+            uses  device:DeviceTypes;
+
+        }
+    }
+
+    rpc VolthaLocalService-GetDeviceType {
+        description
+            "Get additional information on given device type";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  device:DeviceType;
+
+        }
+    }
+
+    rpc VolthaLocalService-ListDeviceGroups {
+        description
+            "List device sharding groups managed by this Voltha instance";
+        input {
+            uses  empty:Empty;
+
+        }
+        output {
+            uses  DeviceGroups;
+
+        }
+    }
+
+    rpc VolthaLocalService-GetDeviceGroup {
+        description
+            "Get more information on given device shard";
+        input {
+            uses  common:ID;
+
+        }
+        output {
+            uses  DeviceGroup;
+
+        }
+    }
+
+    rpc VolthaLocalService-StreamPacketsOut {
+        description
+            "Stream control packets to the dataplane
+This does not have an HTTP representation";
+        input {
+            uses  openflow_13:PacketOut;
+
+        }
+        output {
+            uses  empty:Empty;
+
+        }
+    }
+
+    rpc VolthaLocalService-ReceivePacketsIn {
+        description
+            "Receive control packet stream
+This does not have an HTTP representation";
+        input {
+            uses  empty:Empty;
+
+        }
+        output {
+            uses  openflow_13:PacketIn;
+
+        }
+    }
+
+
+}
\ No newline at end of file
diff --git a/experiments/netconf/proto2yang/logical_device.proto b/experiments/netconf/proto2yang/logical_device.proto
new file mode 100644
index 0000000..94d9588
--- /dev/null
+++ b/experiments/netconf/proto2yang/logical_device.proto
@@ -0,0 +1,52 @@
+syntax = "proto3";
+
+package voltha;
+
+import "meta.proto";
+import "google/api/annotations.proto";
+import "openflow_13.proto";
+
+
+message LogicalPort {
+    string id = 1;
+    openflow_13.ofp_port ofp_port = 2;
+    string device_id = 3;
+    uint32 device_port_no = 4;
+    bool root_port = 5;
+}
+
+message LogicalPorts {
+    repeated LogicalPort items = 1;
+}
+
+message LogicalDevice {
+
+    // unique id of logical device
+    string id = 1;
+
+    // unique datapath id for the logical device (used by the SDN controller)
+    uint64 datapath_id = 2;
+
+    // device description
+    openflow_13.ofp_desc desc = 3;
+
+    // device features
+    openflow_13.ofp_switch_features switch_features = 4;
+
+    // name of the root device anchoring logical device
+    string root_device_id = 5;
+
+    // logical device ports
+    repeated LogicalPort ports = 128 [(child_node) = {key: "id"}];
+
+    // flows configured on the logical device
+    openflow_13.Flows flows = 129 [(child_node) = {}];
+
+    // flow groups configured on the logical device
+    openflow_13.FlowGroups flow_groups = 130 [(child_node) = {}];
+
+}
+
+message LogicalDevices {
+    repeated LogicalDevice items = 1;
+}
diff --git a/experiments/netconf/proto2yang/meta.proto b/experiments/netconf/proto2yang/meta.proto
new file mode 100644
index 0000000..d16668a
--- /dev/null
+++ b/experiments/netconf/proto2yang/meta.proto
@@ -0,0 +1,46 @@
+// Copyright (c) 2015, Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This file contains annotation definitions that can be used to describe
+// a configuration tree.
+
+syntax = "proto3";
+
+package voltha;
+
+import "google/protobuf/descriptor.proto";
+
+message ChildNode {
+    string key = 1;
+}
+
+enum Access {
+    CONFIG = 0;  // read-write, stored
+    READ_ONLY = 1;      // read-only field
+}
+
+extend google.protobuf.FieldOptions {
+
+    // If present, it indicates that this field is stored as external child node
+    // or children nodes in Voltha's internal configuration tree.
+    // If the field is a container field and if the option specifies a key
+    // the child objects will be addressible by that key.
+    ChildNode child_node = 7761772;
+
+    // This annotation can be used to indicate that a field is read-only,
+    // from the perspective of NBI access. Backend plugins and system
+    // internals can update the field but the update requests through the
+    // NBI will ignore for instance a field that is marked as read-only (RO).
+    Access access = 7761773;
+}
diff --git a/experiments/netconf/proto2yang/openflow_13.proto b/experiments/netconf/proto2yang/openflow_13.proto
new file mode 100644
index 0000000..0e403fd
--- /dev/null
+++ b/experiments/netconf/proto2yang/openflow_13.proto
@@ -0,0 +1,2278 @@
+/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
+ * Junior University
+ * Copyright (c) 2011, 2012 Open Networking Foundation
+ *
+ * We are making the OpenFlow specification and associated documentation
+ * (Software) available for public use and benefit with the expectation
+ * that others will use, modify and enhance the Software and contribute
+ * those enhancements back to the community. However, since we would
+ * like to make the Software available for broadest use, with as few
+ * restrictions as possible permission is hereby granted, free of
+ * charge, to any person obtaining a copy of this Software to deal in
+ * the Software under the copyrights without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The name and trademarks of copyright holder(s) may NOT be used in
+ * advertising or publicity pertaining to the Software or any
+ * derivatives without specific, written prior permission.
+ */
+
+/* OpenFlow: protocol between controller and datapath. */
+
+/*
+ * This is a relatively straightforward rendering of OpenFlow message
+ * definitions into protocol buffer messages. We preserved the snake
+ * case syntax, and made the following changes:
+ * - all pad fields dropped
+ * - for each enum value above 0x7fffffff the MSB is dropped. For example,
+ *   0xffffffff is now 0x7fffffff.
+ * - '<type> thing[...]' is replaced with 'repeated <type> thing'
+ * - 'char thing[...]' is replaced with 'string thing'
+ * - 'uint8_t data[...]' is replaced with 'bytes data'
+ * - the following systematic changes are done to various integer types:
+ *   uint8_t  -> uint32
+ *   uint16_t -> uint32
+ *   uint32_t -> uint32
+ *   uint64_t -> uint64
+ * - removed most length, len, size fields where these values can be determined
+ *   from the explicitly encoded length of "repeated" protobuf fields.
+ * - explicit use of enum types whereever it is unambigous (and not used as
+ *   bitmask/flags value.
+ *
+ */
+syntax = "proto3";
+
+package openflow_13;
+
+
+/* Version number:
+ * OpenFlow versions released: 0x01 = 1.0 ; 0x02 = 1.1 ; 0x03 = 1.2
+ *     0x04 = 1.3
+ */
+/* The most significant bit in the version field is reserved and must
+ * be set to zero.
+ */
+//#define OFP_VERSION   0x04
+//#define PIPELINE_TABLES 64
+//#define OFP_MAX_TABLE_NAME_LEN 32
+//#define OFP_MAX_PORT_NAME_LEN  16
+/* Official IANA registered port for OpenFlow. */
+//#define OFP_TCP_PORT  6653
+//#define OFP_SSL_PORT  6653
+
+//#define OFP_ETH_ALEN 6          /* Bytes in an Ethernet address. */
+
+/* Port numbering. Ports are numbered starting from 1. */
+enum ofp_port_no {
+    OFPP_INVALID    = 0;
+
+    /* Maximum number of physical and logical switch ports. */
+    OFPP_MAX        = 0x7fffff00;
+
+    /* Reserved OpenFlow Port (fake output "ports"). */
+    OFPP_IN_PORT    = 0x7ffffff8;  /* Send the packet out the input port.  This
+                                      reserved port must be explicitly used
+                                      in order to send back out of the input
+                                      port. */
+    OFPP_TABLE      = 0x7ffffff9;  /* Submit the packet to the first flow table
+                                      NB: This destination port can only be
+                                      used in packet-out messages. */
+    OFPP_NORMAL     = 0x7ffffffa;  /* Forward using non-OpenFlow pipeline. */
+    OFPP_FLOOD      = 0x7ffffffb;  /* Flood using non-OpenFlow pipeline. */
+    OFPP_ALL        = 0x7ffffffc;  /* All standard ports except input port. */
+    OFPP_CONTROLLER = 0x7ffffffd;  /* Send to controller. */
+    OFPP_LOCAL      = 0x7ffffffe;  /* Local openflow "port". */
+    OFPP_ANY        = 0x7fffffff;  /* Special value used in some requests when
+                                      no port is specified (i.e. wildcarded).*/
+};
+
+enum ofp_type {
+
+    /* Immutable messages. */
+    OFPT_HELLO                      = 0;  /* Symmetric message */
+    OFPT_ERROR                      = 1;  /* Symmetric message */
+    OFPT_ECHO_REQUEST               = 2;  /* Symmetric message */
+    OFPT_ECHO_REPLY                 = 3;  /* Symmetric message */
+    OFPT_EXPERIMENTER               = 4;  /* Symmetric message */
+
+    /* Switch configuration messages. */
+    OFPT_FEATURES_REQUEST           = 5;  /* Controller/switch message */
+    OFPT_FEATURES_REPLY             = 6;  /* Controller/switch message */
+    OFPT_GET_CONFIG_REQUEST         = 7;  /* Controller/switch message */
+    OFPT_GET_CONFIG_REPLY           = 8;  /* Controller/switch message */
+    OFPT_SET_CONFIG                 = 9;  /* Controller/switch message */
+
+    /* Asynchronous messages. */
+    OFPT_PACKET_IN                  = 10; /* Async message */
+    OFPT_FLOW_REMOVED               = 11; /* Async message */
+    OFPT_PORT_STATUS                = 12; /* Async message */
+
+    /* Controller command messages. */
+    OFPT_PACKET_OUT                 = 13; /* Controller/switch message */
+    OFPT_FLOW_MOD                   = 14; /* Controller/switch message */
+    OFPT_GROUP_MOD                  = 15; /* Controller/switch message */
+    OFPT_PORT_MOD                   = 16; /* Controller/switch message */
+    OFPT_TABLE_MOD                  = 17; /* Controller/switch message */
+
+    /* Multipart messages. */
+    OFPT_MULTIPART_REQUEST          = 18; /* Controller/switch message */
+    OFPT_MULTIPART_REPLY            = 19; /* Controller/switch message */
+
+    /* Barrier messages. */
+    OFPT_BARRIER_REQUEST            = 20; /* Controller/switch message */
+    OFPT_BARRIER_REPLY              = 21; /* Controller/switch message */
+
+    /* Queue Configuration messages. */
+    OFPT_QUEUE_GET_CONFIG_REQUEST   = 22;  /* Controller/switch message */
+    OFPT_QUEUE_GET_CONFIG_REPLY     = 23;  /* Controller/switch message */
+
+    /* Controller role change request messages. */
+    OFPT_ROLE_REQUEST               = 24; /* Controller/switch message */
+    OFPT_ROLE_REPLY                 = 25; /* Controller/switch message */
+
+    /* Asynchronous message configuration. */
+    OFPT_GET_ASYNC_REQUEST          = 26; /* Controller/switch message */
+    OFPT_GET_ASYNC_REPLY            = 27; /* Controller/switch message */
+    OFPT_SET_ASYNC                  = 28; /* Controller/switch message */
+
+    /* Meters and rate limiters configuration messages. */
+    OFPT_METER_MOD                  = 29; /* Controller/switch message */
+};
+
+/* Header on all OpenFlow packets. */
+message ofp_header {
+    uint32 version = 1;    /* OFP_VERSION. */
+    ofp_type type = 2;     /* One of the OFPT_ constants. */
+    uint32 xid = 3;        /* Transaction id associated with this packet.
+                              Replies use the same id as was in the request
+                              to facilitate pairing. */
+};
+
+/* Hello elements types.
+ */
+enum ofp_hello_elem_type {
+    OFPHET_INVALID                = 0;
+    OFPHET_VERSIONBITMAP          = 1;  /* Bitmap of version supported. */
+};
+
+/* Common header for all Hello Elements */
+message ofp_hello_elem_header {
+    ofp_hello_elem_type type = 1;       /* One of OFPHET_*. */
+    oneof element {
+        ofp_hello_elem_versionbitmap versionbitmap = 2;
+    }
+};
+
+/* Version bitmap Hello Element */
+message ofp_hello_elem_versionbitmap {
+    repeated uint32 bitmaps = 2;   /* List of bitmaps - supported versions */
+};
+
+/* OFPT_HELLO.  This message includes zero or more hello elements having
+ * variable size. Unknown elements types must be ignored/skipped, to allow
+ * for future extensions. */
+message ofp_hello {
+    //ofp_header header;
+    /* Hello element list */
+    repeated ofp_hello_elem_header elements = 1; /* 0 or more */
+};
+
+//#define OFP_DEFAULT_MISS_SEND_LEN   128
+
+enum ofp_config_flags {
+    /* Handling of IP fragments. */
+    OFPC_FRAG_NORMAL   = 0;       /* No special handling for fragments. */
+    OFPC_FRAG_DROP     = 1;       /* Drop fragments. */
+    OFPC_FRAG_REASM    = 2;       /* Reassemble (only if OFPC_IP_REASM set). */
+    OFPC_FRAG_MASK     = 3;       /* Bitmask of flags dealing with frag. */
+};
+
+/* Switch configuration. */
+message ofp_switch_config {
+    //ofp_header header;
+    uint32 flags = 1;             /* Bitmap of OFPC_* flags. */
+    uint32 miss_send_len = 2;     /* Max bytes of packet that datapath
+                                     should send to the controller. See
+                                     ofp_controller_max_len for valid values.
+                                   */
+};
+
+/* Flags to configure the table. Reserved for future use. */
+enum ofp_table_config {
+    OFPTC_INVALID = 0;
+    OFPTC_DEPRECATED_MASK = 3;     /* Deprecated bits */
+};
+
+/* Table numbering. Tables can use any number up to OFPT_MAX. */
+enum ofp_table {
+
+    OFPTT_INVALID = 0;
+
+    /* Last usable table number. */
+    OFPTT_MAX        = 0xfe;
+
+    /* Fake tables. */
+    OFPTT_ALL        = 0xff;   /* Wildcard table used for table config,
+                                  flow stats and flow deletes. */
+};
+
+
+/* Configure/Modify behavior of a flow table */
+message ofp_table_mod {
+    //ofp_header header;
+    uint32 table_id = 1;  /* ID of the table, OFPTT_ALL indicates all tables */
+    uint32 config = 2;    /* Bitmap of OFPTC_* flags */
+};
+
+/* Capabilities supported by the datapath. */
+enum ofp_capabilities {
+    OFPC_INVALID        = 0;
+    OFPC_FLOW_STATS     = 1;    /* Flow statistics. */
+    OFPC_TABLE_STATS    = 2;    /* Table statistics. */
+    OFPC_PORT_STATS     = 4;    /* Port statistics. */
+    OFPC_GROUP_STATS    = 8;    /* Group statistics. */
+    OFPC_IP_REASM       = 32;   /* Can reassemble IP fragments. */
+    OFPC_QUEUE_STATS    = 64;   /* Queue statistics. */
+    OFPC_PORT_BLOCKED   = 256;  /* Switch will block looping ports. */
+};
+
+/* Flags to indicate behavior of the physical port.  These flags are
+ * used in ofp_port to describe the current configuration.  They are
+ * used in the ofp_port_mod message to configure the port's behavior.
+ */
+enum ofp_port_config {
+    OFPPC_INVALID      = 0;
+    OFPPC_PORT_DOWN    = 1;   /* Port is administratively down. */
+
+    OFPPC_NO_RECV      = 4;   /* Drop all packets received by port. */
+    OFPPC_NO_FWD       = 32;  /* Drop packets forwarded to port. */
+    OFPPC_NO_PACKET_IN = 64;  /* Do not send packet-in msgs for port. */
+};
+
+/* Current state of the physical port.  These are not configurable from
+ * the controller.
+ */
+enum ofp_port_state {
+    OFPPS_INVALID      = 0;
+    OFPPS_LINK_DOWN    = 1;  /* No physical link present. */
+    OFPPS_BLOCKED      = 2;  /* Port is blocked */
+    OFPPS_LIVE         = 4;  /* Live for Fast Failover Group. */
+};
+
+/* Features of ports available in a datapath. */
+enum ofp_port_features {
+    OFPPF_INVALID    = 0;
+    OFPPF_10MB_HD    = 1;      /* 10 Mb half-duplex rate support. */
+    OFPPF_10MB_FD    = 2;      /* 10 Mb full-duplex rate support. */
+    OFPPF_100MB_HD   = 4;      /* 100 Mb half-duplex rate support. */
+    OFPPF_100MB_FD   = 8;      /* 100 Mb full-duplex rate support. */
+    OFPPF_1GB_HD     = 16;     /* 1 Gb half-duplex rate support. */
+    OFPPF_1GB_FD     = 32;     /* 1 Gb full-duplex rate support. */
+    OFPPF_10GB_FD    = 64;     /* 10 Gb full-duplex rate support. */
+    OFPPF_40GB_FD    = 128;    /* 40 Gb full-duplex rate support. */
+    OFPPF_100GB_FD   = 256;    /* 100 Gb full-duplex rate support. */
+    OFPPF_1TB_FD     = 512;    /* 1 Tb full-duplex rate support. */
+    OFPPF_OTHER      = 1024;   /* Other rate, not in the list. */
+    OFPPF_COPPER     = 2048;   /* Copper medium. */
+    OFPPF_FIBER      = 4096;   /* Fiber medium. */
+    OFPPF_AUTONEG    = 8192;   /* Auto-negotiation. */
+    OFPPF_PAUSE      = 16384;  /* Pause. */
+    OFPPF_PAUSE_ASYM = 32768;  /* Asymmetric pause. */
+};
+
+/* Description of a port */
+message ofp_port {
+    uint32 port_no = 1;
+    repeated uint32 hw_addr = 2; // [OFP_ETH_ALEN];
+    string name = 3;             /* Null-terminated */
+
+    uint32 config = 4;           /* Bitmap of OFPPC_* flags. */
+    uint32 state = 5;            /* Bitmap of OFPPS_* flags. */
+
+    /* Bitmaps of OFPPF_* that describe features.  All bits zeroed if
+     * unsupported or unavailable. */
+    uint32 curr = 6;           /* Current features. */
+    uint32 advertised = 7;     /* Features being advertised by the port. */
+    uint32 supported = 8;      /* Features supported by the port. */
+    uint32 peer = 9;           /* Features advertised by peer. */
+    uint32 curr_speed = 10;    /* Current port bitrate in kbps. */
+    uint32 max_speed = 11;     /* Max port bitrate in kbps */
+};
+
+/* Switch features. */
+message ofp_switch_features {
+    //ofp_header header;
+    uint64 datapath_id = 1;   /* Datapath unique ID.  The lower 48-bits are for
+                                 a MAC address, while the upper 16-bits are
+                                 implementer-defined. */
+
+    uint32 n_buffers = 2;     /* Max packets buffered at once. */
+
+    uint32 n_tables = 3;      /* Number of tables supported by datapath. */
+    uint32 auxiliary_id = 4;  /* Identify auxiliary connections */
+
+    /* Features. */
+    uint32 capabilities = 5;  /* Bitmap of support "ofp_capabilities". */
+};
+
+/* What changed about the physical port */
+enum ofp_port_reason {
+    OFPPR_ADD     = 0;         /* The port was added. */
+    OFPPR_DELETE  = 1;         /* The port was removed. */
+    OFPPR_MODIFY  = 2;         /* Some attribute of the port has changed. */
+};
+
+/* A physical port has changed in the datapath */
+message ofp_port_status {
+    //ofp_header header;
+    ofp_port_reason reason = 1; /* One of OFPPR_*. */
+    ofp_port desc = 2;
+};
+
+/* Modify behavior of the physical port */
+message ofp_port_mod {
+    //ofp_header header;
+    uint32 port_no = 1;
+    repeated uint32 hw_addr = 2; //[OFP_ETH_ALEN];
+                                      /* The hardware address is not
+                                         configurable.  This is used to
+                                         sanity-check the request, so it must
+                                         be the same as returned in an
+                                         ofp_port struct. */
+    uint32 config = 3;        /* Bitmap of OFPPC_* flags. */
+    uint32 mask = 4;          /* Bitmap of OFPPC_* flags to be changed. */
+
+    uint32 advertise = 5;     /* Bitmap of OFPPF_*.  Zero all bits to prevent
+                                 any action taking place. */
+};
+
+/* ## -------------------------- ## */
+/* ## OpenFlow Extensible Match. ## */
+/* ## -------------------------- ## */
+
+/* The match type indicates the match structure (set of fields that compose the
+ * match) in use. The match type is placed in the type field at the beginning
+ * of all match structures. The "OpenFlow Extensible Match" type corresponds
+ * to OXM TLV format described below and must be supported by all OpenFlow
+ * switches. Extensions that define other match types may be published on the
+ * ONF wiki. Support for extensions is optional.
+ */
+enum ofp_match_type {
+    OFPMT_STANDARD = 0;       /* Deprecated. */
+    OFPMT_OXM      = 1;       /* OpenFlow Extensible Match */
+};
+
+/* Fields to match against flows */
+message ofp_match {
+    ofp_match_type type = 1;         /* One of OFPMT_* */
+    repeated ofp_oxm_field oxm_fields = 2;  /* 0 or more */
+};
+
+/* Components of a OXM TLV header.
+ * Those macros are not valid for the experimenter class, macros for the
+ * experimenter class will depend on the experimenter header used. */
+//#define OXM_HEADER__(CLASS, FIELD, HASMASK, LENGTH) \
+//    (((CLASS) << 16) | ((FIELD) << 9) | ((HASMASK) << 8) | (LENGTH))
+//#define OXM_HEADER(CLASS, FIELD, LENGTH) \
+//    OXM_HEADER__(CLASS, FIELD, 0, LENGTH)
+//#define OXM_HEADER_W(CLASS, FIELD, LENGTH) \
+//    OXM_HEADER__(CLASS, FIELD, 1, (LENGTH) * 2)
+//#define OXM_CLASS(HEADER) ((HEADER) >> 16)
+//#define OXM_FIELD(HEADER) (((HEADER) >> 9) & 0x7f)
+//#define OXM_TYPE(HEADER) (((HEADER) >> 9) & 0x7fffff)
+//#define OXM_HASMASK(HEADER) (((HEADER) >> 8) & 1)
+//#define OXM_LENGTH(HEADER) ((HEADER) & 0xff)
+//
+//#define OXM_MAKE_WILD_HEADER(HEADER) \
+//    OXM_HEADER_W(OXM_CLASS(HEADER), OXM_FIELD(HEADER), OXM_LENGTH(HEADER))
+
+/* OXM Class IDs.
+ * The high order bit differentiate reserved classes from member classes.
+ * Classes 0x0000 to 0x7FFF are member classes, allocated by ONF.
+ * Classes 0x8000 to 0xFFFE are reserved classes, reserved for standardisation.
+ */
+enum ofp_oxm_class {
+    OFPXMC_NXM_0          = 0x0000;    /* Backward compatibility with NXM */
+    OFPXMC_NXM_1          = 0x0001;    /* Backward compatibility with NXM */
+    OFPXMC_OPENFLOW_BASIC = 0x8000;    /* Basic class for OpenFlow */
+    OFPXMC_EXPERIMENTER   = 0xFFFF;    /* Experimenter class */
+};
+
+/* OXM Flow field types for OpenFlow basic class. */
+enum oxm_ofb_field_types {
+    OFPXMT_OFB_IN_PORT        = 0;  /* Switch input port. */
+    OFPXMT_OFB_IN_PHY_PORT    = 1;  /* Switch physical input port. */
+    OFPXMT_OFB_METADATA       = 2;  /* Metadata passed between tables. */
+    OFPXMT_OFB_ETH_DST        = 3;  /* Ethernet destination address. */
+    OFPXMT_OFB_ETH_SRC        = 4;  /* Ethernet source address. */
+    OFPXMT_OFB_ETH_TYPE       = 5;  /* Ethernet frame type. */
+    OFPXMT_OFB_VLAN_VID       = 6;  /* VLAN id. */
+    OFPXMT_OFB_VLAN_PCP       = 7;  /* VLAN priority. */
+    OFPXMT_OFB_IP_DSCP        = 8;  /* IP DSCP (6 bits in ToS field). */
+    OFPXMT_OFB_IP_ECN         = 9;  /* IP ECN (2 bits in ToS field). */
+    OFPXMT_OFB_IP_PROTO       = 10; /* IP protocol. */
+    OFPXMT_OFB_IPV4_SRC       = 11; /* IPv4 source address. */
+    OFPXMT_OFB_IPV4_DST       = 12; /* IPv4 destination address. */
+    OFPXMT_OFB_TCP_SRC        = 13; /* TCP source port. */
+    OFPXMT_OFB_TCP_DST        = 14; /* TCP destination port. */
+    OFPXMT_OFB_UDP_SRC        = 15; /* UDP source port. */
+    OFPXMT_OFB_UDP_DST        = 16; /* UDP destination port. */
+    OFPXMT_OFB_SCTP_SRC       = 17; /* SCTP source port. */
+    OFPXMT_OFB_SCTP_DST       = 18; /* SCTP destination port. */
+    OFPXMT_OFB_ICMPV4_TYPE    = 19; /* ICMP type. */
+    OFPXMT_OFB_ICMPV4_CODE    = 20; /* ICMP code. */
+    OFPXMT_OFB_ARP_OP         = 21; /* ARP opcode. */
+    OFPXMT_OFB_ARP_SPA        = 22; /* ARP source IPv4 address. */
+    OFPXMT_OFB_ARP_TPA        = 23; /* ARP target IPv4 address. */
+    OFPXMT_OFB_ARP_SHA        = 24; /* ARP source hardware address. */
+    OFPXMT_OFB_ARP_THA        = 25; /* ARP target hardware address. */
+    OFPXMT_OFB_IPV6_SRC       = 26; /* IPv6 source address. */
+    OFPXMT_OFB_IPV6_DST       = 27; /* IPv6 destination address. */
+    OFPXMT_OFB_IPV6_FLABEL    = 28; /* IPv6 Flow Label */
+    OFPXMT_OFB_ICMPV6_TYPE    = 29; /* ICMPv6 type. */
+    OFPXMT_OFB_ICMPV6_CODE    = 30; /* ICMPv6 code. */
+    OFPXMT_OFB_IPV6_ND_TARGET = 31; /* Target address for ND. */
+    OFPXMT_OFB_IPV6_ND_SLL    = 32; /* Source link-layer for ND. */
+    OFPXMT_OFB_IPV6_ND_TLL    = 33; /* Target link-layer for ND. */
+    OFPXMT_OFB_MPLS_LABEL     = 34; /* MPLS label. */
+    OFPXMT_OFB_MPLS_TC        = 35; /* MPLS TC. */
+    OFPXMT_OFB_MPLS_BOS       = 36; /* MPLS BoS bit. */
+    OFPXMT_OFB_PBB_ISID       = 37; /* PBB I-SID. */
+    OFPXMT_OFB_TUNNEL_ID      = 38; /* Logical Port Metadata. */
+    OFPXMT_OFB_IPV6_EXTHDR    = 39; /* IPv6 Extension Header pseudo-field */
+};
+
+/* OXM Flow match fields */
+message ofp_oxm_field {
+    ofp_oxm_class oxm_class = 1;
+    oneof field {
+        /* 2 and 3 reserved for NXM_0 and NXM-1 OXM classes */
+        ofp_oxm_ofb_field ofb_field = 4;
+        ofp_oxm_experimenter_field experimenter_field = 5;
+    }
+}
+
+/* OXM OpenFlow Basic Match Field */
+message ofp_oxm_ofb_field {
+    oxm_ofb_field_types type = 1;
+    bool has_mask = 2;
+    oneof value {
+
+        /* OpenFlow port on which the packet was received.
+         * May be a physical port, a logical port, or the reserved port OFPP_LOCAL
+         *
+         * Prereqs: None.
+         *
+         * Format: 32-bit integer in network byte order.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_IN_PORT    OXM_HEADER  (0x8000, OFPXMT_OFB_IN_PORT, 4)
+        uint32 port = 3; /* Used for OFPXMT_OFB_IN_PORT */
+
+        /* Physical port on which the packet was received.
+         *
+         * Consider a packet received on a tunnel interface defined over a link
+         * aggregation group (LAG) with two physical port members.  If the tunnel
+         * interface is the logical port bound to OpenFlow.  In this case,
+         * OFPXMT_OF_IN_PORT is the tunnel's port number and OFPXMT_OF_IN_PHY_PORT is
+         * the physical port number of the LAG on which the tunnel is configured.
+         *
+         * When a packet is received directly on a physical port and not processed by a
+         * logical port, OFPXMT_OF_IN_PORT and OFPXMT_OF_IN_PHY_PORT have the same
+         * value.
+         *
+         * This field is usually not available in a regular match and only available
+         * in ofp_packet_in messages when it's different from OXM_OF_IN_PORT.
+         *
+         * Prereqs: OXM_OF_IN_PORT must be present.
+         *
+         * Format: 32-bit integer in network byte order.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_IN_PHY_PORT OXM_HEADER  (0x8000, OFPXMT_OFB_IN_PHY_PORT, 4)
+        uint32 physical_port = 4; /* Used for OFPXMT_OF_IN_PHY_PORT */
+
+        /* Table metadata.
+         *
+         * Prereqs: None.
+         *
+         * Format: 64-bit integer in network byte order.
+         *
+         * Masking: Arbitrary masks.
+         */
+        //#define OXM_OF_METADATA   OXM_HEADER  (0x8000, OFPXMT_OFB_METADATA, 8)
+        //#define OXM_OF_METADATA_W OXM_HEADER_W(0x8000, OFPXMT_OFB_METADATA, 8)
+        uint64 table_metadata = 5; /* Used for OFPXMT_OFB_METADATA */
+
+        /* Source or destination address in Ethernet header.
+         *
+         * Prereqs: None.
+         *
+         * Format: 48-bit Ethernet MAC address.
+         *
+         * Masking: Arbitrary masks. */
+        //#define OXM_OF_ETH_DST    OXM_HEADER  (0x8000, OFPXMT_OFB_ETH_DST, 6)
+        //#define OXM_OF_ETH_DST_W  OXM_HEADER_W(0x8000, OFPXMT_OFB_ETH_DST, 6)
+        //#define OXM_OF_ETH_SRC    OXM_HEADER  (0x8000, OFPXMT_OFB_ETH_SRC, 6)
+        //#define OXM_OF_ETH_SRC_W  OXM_HEADER_W(0x8000, OFPXMT_OFB_ETH_SRC, 6)
+        bytes eth_dst = 6; /* Used for OFPXMT_OFB_ETH_DST (exactly 6 bytes) */
+        bytes eth_src = 7; /* Used for OFPXMT_OFB_ETH_SRC (exactly 6 bytes) */
+
+        /* Packet's Ethernet type.
+         *
+         * Prereqs: None.
+         *
+         * Format: 16-bit integer in network byte order.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_ETH_TYPE   OXM_HEADER  (0x8000, OFPXMT_OFB_ETH_TYPE,2)
+        uint32 eth_type = 8; /* Used for OFPXMT_OFB_ETH_TYPE */
+
+        /* 802.1Q VID.
+         *
+         * For a packet with an 802.1Q header, this is the VLAN-ID (VID) from the
+         * outermost tag, with the CFI bit forced to 1. For a packet with no 802.1Q
+         * header, this has value OFPVID_NONE.
+         *
+         * Prereqs: None.
+         *
+         * Format: 16-bit integer in network byte order with bit 13 indicating
+         * presence of VLAN header and 3 most-significant bits forced to 0.
+         * Only the lower 13 bits have meaning.
+         *
+         * Masking: Arbitrary masks.
+         *
+         * This field can be used in various ways:
+         *
+         *   - If it is not constrained at all, the nx_match matches packets without
+         *     an 802.1Q header or with an 802.1Q header that has any VID value.
+         *
+         *   - Testing for an exact match with 0x0 matches only packets without
+         *     an 802.1Q header.
+         *
+         *   - Testing for an exact match with a VID value with CFI=1 matches packets
+         *     that have an 802.1Q header with a specified VID.
+         *
+         *   - Testing for an exact match with a nonzero VID value with CFI=0 does
+         *     not make sense.  The switch may reject this combination.
+         *
+         *   - Testing with nxm_value=0, nxm_mask=0x0fff matches packets with no 802.1Q
+         *     header or with an 802.1Q header with a VID of 0.
+         *
+         *   - Testing with nxm_value=0x1000, nxm_mask=0x1000 matches packets with
+         *     an 802.1Q header that has any VID value.
+         */
+        //#define OXM_OF_VLAN_VID   OXM_HEADER  (0x8000, OFPXMT_OFB_VLAN_VID, 2)
+        //#define OXM_OF_VLAN_VID_W OXM_HEADER_W(0x8000, OFPXMT_OFB_VLAN_VID, 2)
+        uint32 vlan_vid = 9; /* Used for OFPXMT_OFB_VLAN_VID */
+
+        /* 802.1Q PCP.
+         *
+         * For a packet with an 802.1Q header, this is the VLAN-PCP from the
+         * outermost tag.  For a packet with no 802.1Q header, this has value
+         * 0.
+         *
+         * Prereqs: OXM_OF_VLAN_VID must be different from OFPVID_NONE.
+         *
+         * Format: 8-bit integer with 5 most-significant bits forced to 0.
+         * Only the lower 3 bits have meaning.
+         *
+         * Masking: Not maskable.
+         */
+        //#define OXM_OF_VLAN_PCP   OXM_HEADER  (0x8000, OFPXMT_OFB_VLAN_PCP, 1)
+        uint32 vlan_pcp = 10; /* Used for OFPXMT_OFB_VLAN_PCP */
+
+        /* The Diff Serv Code Point (DSCP) bits of the IP header.
+         * Part of the IPv4 ToS field or the IPv6 Traffic Class field.
+         *
+         * Prereqs: OXM_OF_ETH_TYPE must be either 0x0800 or 0x86dd.
+         *
+         * Format: 8-bit integer with 2 most-significant bits forced to 0.
+         * Only the lower 6 bits have meaning.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_IP_DSCP     OXM_HEADER  (0x8000, OFPXMT_OFB_IP_DSCP, 1)
+        uint32 ip_dscp = 11; /* Used for OFPXMT_OFB_IP_DSCP */
+
+        /* The ECN bits of the IP header.
+         * Part of the IPv4 ToS field or the IPv6 Traffic Class field.
+         *
+         * Prereqs: OXM_OF_ETH_TYPE must be either 0x0800 or 0x86dd.
+         *
+         * Format: 8-bit integer with 6 most-significant bits forced to 0.
+         * Only the lower 2 bits have meaning.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_IP_ECN     OXM_HEADER  (0x8000, OFPXMT_OFB_IP_ECN, 1)
+        uint32 ip_ecn = 12; /* Used for OFPXMT_OFB_IP_ECN */
+
+        /* The "protocol" byte in the IP header.
+         *
+         * Prereqs: OXM_OF_ETH_TYPE must be either 0x0800 or 0x86dd.
+         *
+         * Format: 8-bit integer.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_IP_PROTO   OXM_HEADER  (0x8000, OFPXMT_OFB_IP_PROTO, 1)
+        uint32 ip_proto = 13; /* Used for OFPXMT_OFB_IP_PROTO */
+
+        /* The source or destination address in the IP header.
+         *
+         * Prereqs: OXM_OF_ETH_TYPE must match 0x0800 exactly.
+         *
+         * Format: 32-bit integer in network byte order.
+         *
+         * Masking: Arbitrary masks.
+         */
+        //#define OXM_OF_IPV4_SRC     OXM_HEADER  (0x8000, OFPXMT_OFB_IPV4_SRC, 4)
+        //#define OXM_OF_IPV4_SRC_W   OXM_HEADER_W(0x8000, OFPXMT_OFB_IPV4_SRC, 4)
+        //#define OXM_OF_IPV4_DST     OXM_HEADER  (0x8000, OFPXMT_OFB_IPV4_DST, 4)
+        //#define OXM_OF_IPV4_DST_W   OXM_HEADER_W(0x8000, OFPXMT_OFB_IPV4_DST, 4)
+        uint32 ipv4_src = 14; /* Used for OFPXMT_OFB_IPV4_SRC */
+        uint32 ipv4_dst = 15; /* Used for OFPXMT_OFB_IPV4_DST */
+
+        /* The source or destination port in the TCP header.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must be either 0x0800 or 0x86dd.
+         *   OXM_OF_IP_PROTO must match 6 exactly.
+         *
+         * Format: 16-bit integer in network byte order.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_TCP_SRC    OXM_HEADER  (0x8000, OFPXMT_OFB_TCP_SRC, 2)
+        //#define OXM_OF_TCP_DST    OXM_HEADER  (0x8000, OFPXMT_OFB_TCP_DST, 2)
+        uint32 tcp_src = 16; /* Used for OFPXMT_OFB_TCP_SRC */
+        uint32 tcp_dst = 17; /* Used for OFPXMT_OFB_TCP_DST */
+
+        /* The source or destination port in the UDP header.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match either 0x0800 or 0x86dd.
+         *   OXM_OF_IP_PROTO must match 17 exactly.
+         *
+         * Format: 16-bit integer in network byte order.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_UDP_SRC    OXM_HEADER  (0x8000, OFPXMT_OFB_UDP_SRC, 2)
+        //#define OXM_OF_UDP_DST    OXM_HEADER  (0x8000, OFPXMT_OFB_UDP_DST, 2)
+        uint32 udp_src = 18; /* Used for OFPXMT_OFB_UDP_SRC */
+        uint32 udp_dst = 19; /* Used for OFPXMT_OFB_UDP_DST */
+
+        /* The source or destination port in the SCTP header.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match either 0x0800 or 0x86dd.
+         *   OXM_OF_IP_PROTO must match 132 exactly.
+         *
+         * Format: 16-bit integer in network byte order.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_SCTP_SRC   OXM_HEADER  (0x8000, OFPXMT_OFB_SCTP_SRC, 2)
+        //#define OXM_OF_SCTP_DST   OXM_HEADER  (0x8000, OFPXMT_OFB_SCTP_DST, 2)
+        uint32 sctp_src = 20; /* Used for OFPXMT_OFB_SCTP_SRC */
+        uint32 sctp_dst = 21; /* Used for OFPXMT_OFB_SCTP_DST */
+
+        /* The type or code in the ICMP header.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match 0x0800 exactly.
+         *   OXM_OF_IP_PROTO must match 1 exactly.
+         *
+         * Format: 8-bit integer.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_ICMPV4_TYPE  OXM_HEADER  (0x8000, OFPXMT_OFB_ICMPV4_TYPE, 1)
+        //#define OXM_OF_ICMPV4_CODE  OXM_HEADER  (0x8000, OFPXMT_OFB_ICMPV4_CODE, 1)
+        uint32 icmpv4_type = 22; /* Used for OFPXMT_OFB_ICMPV4_TYPE */
+        uint32 icmpv4_code = 23; /* Used for OFPXMT_OFB_ICMPV4_CODE */
+
+        /* ARP opcode.
+         *
+         * For an Ethernet+IP ARP packet, the opcode in the ARP header.  Always 0
+         * otherwise.
+         *
+         * Prereqs: OXM_OF_ETH_TYPE must match 0x0806 exactly.
+         *
+         * Format: 16-bit integer in network byte order.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_ARP_OP     OXM_HEADER  (0x8000, OFPXMT_OFB_ARP_OP, 2)
+        uint32 arp_op = 24; /* Used for OFPXMT_OFB_ARP_OP */
+
+        /* For an Ethernet+IP ARP packet, the source or target protocol address
+         * in the ARP header.  Always 0 otherwise.
+         *
+         * Prereqs: OXM_OF_ETH_TYPE must match 0x0806 exactly.
+         *
+         * Format: 32-bit integer in network byte order.
+         *
+         * Masking: Arbitrary masks.
+         */
+        //#define OXM_OF_ARP_SPA    OXM_HEADER  (0x8000, OFPXMT_OFB_ARP_SPA, 4)
+        //#define OXM_OF_ARP_SPA_W  OXM_HEADER_W(0x8000, OFPXMT_OFB_ARP_SPA, 4)
+        //#define OXM_OF_ARP_TPA    OXM_HEADER  (0x8000, OFPXMT_OFB_ARP_TPA, 4)
+        //#define OXM_OF_ARP_TPA_W  OXM_HEADER_W(0x8000, OFPXMT_OFB_ARP_TPA, 4)
+        uint32 arp_spa = 25; /* For OFPXMT_OFB_ARP_SPA */
+        uint32 arp_tpa = 26; /* For OFPXMT_OFB_ARP_TPA */
+
+        /* For an Ethernet+IP ARP packet, the source or target hardware address
+         * in the ARP header.  Always 0 otherwise.
+         *
+         * Prereqs: OXM_OF_ETH_TYPE must match 0x0806 exactly.
+         *
+         * Format: 48-bit Ethernet MAC address.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_ARP_SHA    OXM_HEADER   (0x8000, OFPXMT_OFB_ARP_SHA, 6)
+        //#define OXM_OF_ARP_SHA_W  OXM_HEADER_W (0x8000, OFPXMT_OFB_ARP_SHA, 6)
+        //#define OXM_OF_ARP_THA    OXM_HEADER   (0x8000, OFPXMT_OFB_ARP_THA, 6)
+        //#define OXM_OF_ARP_THA_W  OXM_HEADER_W (0x8000, OFPXMT_OFB_ARP_THA, 6)
+        bytes arp_sha = 27; /* For OFPXMT_OFB_ARP_SHA (6 bytes) */
+        bytes arp_tha = 28; /* For OFPXMT_OFB_ARP_THA (6 bytes) */
+
+        /* The source or destination address in the IPv6 header.
+         *
+         * Prereqs: OXM_OF_ETH_TYPE must match 0x86dd exactly.
+         *
+         * Format: 128-bit IPv6 address.
+         *
+         * Masking: Arbitrary masks.
+         */
+        //#define OXM_OF_IPV6_SRC    OXM_HEADER  (0x8000, OFPXMT_OFB_IPV6_SRC, 16)
+        //#define OXM_OF_IPV6_SRC_W  OXM_HEADER_W(0x8000, OFPXMT_OFB_IPV6_SRC, 16)
+        //#define OXM_OF_IPV6_DST    OXM_HEADER  (0x8000, OFPXMT_OFB_IPV6_DST, 16)
+        //#define OXM_OF_IPV6_DST_W  OXM_HEADER_W(0x8000, OFPXMT_OFB_IPV6_DST, 16)
+        bytes ipv6_src = 29; /* For OFPXMT_OFB_IPV6_SRC */
+        bytes ipv6_dst = 30; /* For OFPXMT_OFB_IPV6_DST */
+
+        /* The IPv6 Flow Label
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match 0x86dd exactly
+         *
+         * Format: 32-bit integer with 12 most-significant bits forced to 0.
+         * Only the lower 20 bits have meaning.
+         *
+         * Masking: Arbitrary masks.
+         */
+        //#define OXM_OF_IPV6_FLABEL   OXM_HEADER  (0x8000, OFPXMT_OFB_IPV6_FLABEL, 4)
+        //#define OXM_OF_IPV6_FLABEL_W OXM_HEADER_W(0x8000, OFPXMT_OFB_IPV6_FLABEL, 4)
+        uint32 ipv6_flabel = 31; /* For OFPXMT_OFB_IPV6_FLABEL */
+
+        /* The type or code in the ICMPv6 header.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match 0x86dd exactly.
+         *   OXM_OF_IP_PROTO must match 58 exactly.
+         *
+         * Format: 8-bit integer.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_ICMPV6_TYPE OXM_HEADER  (0x8000, OFPXMT_OFB_ICMPV6_TYPE, 1)
+        //#define OXM_OF_ICMPV6_CODE OXM_HEADER  (0x8000, OFPXMT_OFB_ICMPV6_CODE, 1)
+        uint32 icmpv6_type = 32; /* For OFPXMT_OFB_ICMPV6_TYPE */
+        uint32 icmpv6_code = 33; /* For OFPXMT_OFB_ICMPV6_CODE */
+
+        /* The target address in an IPv6 Neighbor Discovery message.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match 0x86dd exactly.
+         *   OXM_OF_IP_PROTO must match 58 exactly.
+         *   OXM_OF_ICMPV6_TYPE must be either 135 or 136.
+         *
+         * Format: 128-bit IPv6 address.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_IPV6_ND_TARGET OXM_HEADER \
+        //    (0x8000, OFPXMT_OFB_IPV6_ND_TARGET, 16)
+        bytes ipv6_nd_target = 34; /* For OFPXMT_OFB_IPV6_ND_TARGET */
+
+        /* The source link-layer address option in an IPv6 Neighbor Discovery
+         * message.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match 0x86dd exactly.
+         *   OXM_OF_IP_PROTO must match 58 exactly.
+         *   OXM_OF_ICMPV6_TYPE must be exactly 135.
+         *
+         * Format: 48-bit Ethernet MAC address.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_IPV6_ND_SLL  OXM_HEADER  (0x8000, OFPXMT_OFB_IPV6_ND_SLL, 6)
+        bytes ipv6_nd_ssl = 35; /* For OFPXMT_OFB_IPV6_ND_SLL */
+
+        /* The target link-layer address option in an IPv6 Neighbor Discovery
+         * message.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match 0x86dd exactly.
+         *   OXM_OF_IP_PROTO must match 58 exactly.
+         *   OXM_OF_ICMPV6_TYPE must be exactly 136.
+         *
+         * Format: 48-bit Ethernet MAC address.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_IPV6_ND_TLL  OXM_HEADER  (0x8000, OFPXMT_OFB_IPV6_ND_TLL, 6)
+        bytes ipv6_nd_tll = 36; /* For OFPXMT_OFB_IPV6_ND_TLL */
+
+        /* The LABEL in the first MPLS shim header.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match 0x8847 or 0x8848 exactly.
+         *
+         * Format: 32-bit integer in network byte order with 12 most-significant
+         * bits forced to 0. Only the lower 20 bits have meaning.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_MPLS_LABEL  OXM_HEADER  (0x8000, OFPXMT_OFB_MPLS_LABEL, 4)
+        uint32 mpls_label = 37; /* For OFPXMT_OFB_MPLS_LABEL */
+
+        /* The TC in the first MPLS shim header.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match 0x8847 or 0x8848 exactly.
+         *
+         * Format: 8-bit integer with 5 most-significant bits forced to 0.
+         * Only the lower 3 bits have meaning.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_MPLS_TC     OXM_HEADER  (0x8000, OFPXMT_OFB_MPLS_TC, 1)
+        uint32 mpls_tc = 38; /* For OFPXMT_OFB_MPLS_TC */
+
+        /* The BoS bit in the first MPLS shim header.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match 0x8847 or 0x8848 exactly.
+         *
+         * Format: 8-bit integer with 7 most-significant bits forced to 0.
+         * Only the lowest bit have a meaning.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_MPLS_BOS     OXM_HEADER  (0x8000, OFPXMT_OFB_MPLS_BOS, 1)
+        uint32 mpls_bos = 39; /* For OFPXMT_OFB_MPLS_BOS */
+
+        /* IEEE 802.1ah I-SID.
+         *
+         * For a packet with a PBB header, this is the I-SID from the
+         * outermost service tag.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match 0x88E7 exactly.
+         *
+         * Format: 24-bit integer in network byte order.
+         *
+         * Masking: Arbitrary masks. */
+        //#define OXM_OF_PBB_ISID   OXM_HEADER  (0x8000, OFPXMT_OFB_PBB_ISID, 3)
+        //#define OXM_OF_PBB_ISID_W OXM_HEADER_W(0x8000, OFPXMT_OFB_PBB_ISID, 3)
+        uint32 pbb_isid = 40; /* For OFPXMT_OFB_PBB_ISID */
+
+        /* Logical Port Metadata.
+         *
+         * Metadata associated with a logical port.
+         * If the logical port performs encapsulation and decapsulation, this
+         * is the demultiplexing field from the encapsulation header.
+         * For example, for a packet received via GRE tunnel including a (32-bit) key,
+         * the key is stored in the low 32-bits and the high bits are zeroed.
+         * For a MPLS logical port, the low 20 bits represent the MPLS Label.
+         * For a VxLAN logical port, the low 24 bits represent the VNI.
+         * If the packet is not received through a logical port, the value is 0.
+         *
+         * Prereqs: None.
+         *
+         * Format: 64-bit integer in network byte order.
+         *
+         * Masking: Arbitrary masks. */
+        //#define OXM_OF_TUNNEL_ID    OXM_HEADER  (0x8000, OFPXMT_OFB_TUNNEL_ID, 8)
+        //#define OXM_OF_TUNNEL_ID_W  OXM_HEADER_W(0x8000, OFPXMT_OFB_TUNNEL_ID, 8)
+        uint64 tunnel_id = 41; /* For OFPXMT_OFB_TUNNEL_ID */
+
+        /* The IPv6 Extension Header pseudo-field.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match 0x86dd exactly
+         *
+         * Format: 16-bit integer with 7 most-significant bits forced to 0.
+         * Only the lower 9 bits have meaning.
+         *
+         * Masking: Maskable. */
+        //#define OXM_OF_IPV6_EXTHDR   OXM_HEADER  (0x8000, OFPXMT_OFB_IPV6_EXTHDR, 2)
+        //#define OXM_OF_IPV6_EXTHDR_W OXM_HEADER_W(0x8000, OFPXMT_OFB_IPV6_EXTHDR, 2)
+        uint32 ipv6_exthdr = 42; /* For OFPXMT_OFB_IPV6_EXTHDR */
+
+    }
+
+    /* Optional mask values (must be present when has_mask is true */
+    oneof mask {
+        uint64 table_metadata_mask = 105; /* For OFPXMT_OFB_METADATA */
+
+        bytes eth_dst_mask = 106; /* For OFPXMT_OFB_ETH_DST (exactly 6 bytes)*/
+        bytes eth_src_mask = 107; /* For OFPXMT_OFB_ETH_SRC (exactly 6 bytes)*/
+
+        uint32 vlan_vid_mask = 109; /* For OFPXMT_OFB_VLAN_VID */
+
+        uint32 ipv4_src_mask = 114; /* For OFPXMT_OFB_IPV4_SRC */
+        uint32 ipv4_dst_mask = 115; /* For OFPXMT_OFB_IPV4_DST */
+
+        uint32 arp_spa_mask = 125; /* For OFPXMT_OFB_ARP_SPA */
+        uint32 arp_tpa_mask = 126; /* For OFPXMT_OFB_ARP_TPA */
+
+        bytes ipv6_src_mask = 129; /* For OFPXMT_OFB_IPV6_SRC */
+        bytes ipv6_dst_mask = 130; /* For OFPXMT_OFB_IPV6_DST */
+
+        uint32 ipv6_flabel_mask = 131; /* For OFPXMT_OFB_IPV6_FLABEL */
+
+        uint32 pbb_isid_mask = 140; /* For OFPXMT_OFB_PBB_ISID */
+
+        uint64 tunnel_id_mask = 141; /* For OFPXMT_OFB_TUNNEL_ID */
+
+        uint32 ipv6_exthdr_mask = 142; /* For OFPXMT_OFB_IPV6_EXTHDR */
+    }
+
+}
+//#define OFPXMT_OFB_ALL    ((UINT64_C(1) << 40) - 1)
+
+
+/* The VLAN id is 12-bits, so we can use the entire 16 bits to indicate
+ * special conditions.
+ */
+enum ofp_vlan_id {
+    OFPVID_NONE    = 0x0000; /* No VLAN id was set. */
+    OFPVID_PRESENT = 0x1000; /* Bit that indicate that a VLAN id is set */
+};
+/* Define for compatibility */
+//#define OFP_VLAN_NONE      OFPVID_NONE
+
+/* Bit definitions for IPv6 Extension Header pseudo-field. */
+enum ofp_ipv6exthdr_flags {
+    OFPIEH_INVALID = 0;
+    OFPIEH_NONEXT  = 1;     /* "No next header" encountered. */
+    OFPIEH_ESP     = 2;     /* Encrypted Sec Payload header present. */
+    OFPIEH_AUTH    = 4;     /* Authentication header present. */
+    OFPIEH_DEST    = 8;     /* 1 or 2 dest headers present. */
+    OFPIEH_FRAG    = 16;    /* Fragment header present. */
+    OFPIEH_ROUTER  = 32;    /* Router header present. */
+    OFPIEH_HOP     = 64;    /* Hop-by-hop header present. */
+    OFPIEH_UNREP   = 128;   /* Unexpected repeats encountered. */
+    OFPIEH_UNSEQ   = 256;   /* Unexpected sequencing encountered. */
+};
+
+/* Header for OXM experimenter match fields.
+ * The experimenter class should not use OXM_HEADER() macros for defining
+ * fields due to this extra header. */
+message ofp_oxm_experimenter_field {
+    uint32 oxm_header = 1;    /* oxm_class = OFPXMC_EXPERIMENTER */
+    uint32 experimenter = 2;  /* Experimenter ID which takes the same
+                                 form as in struct ofp_experimenter_header. */
+};
+
+/* ## ----------------- ## */
+/* ## OpenFlow Actions. ## */
+/* ## ----------------- ## */
+
+enum ofp_action_type {
+    OFPAT_OUTPUT       = 0;  /* Output to switch port. */
+    OFPAT_COPY_TTL_OUT = 11; /* Copy TTL "outwards" -- from next-to-outermost
+                                to outermost */
+    OFPAT_COPY_TTL_IN  = 12; /* Copy TTL "inwards" -- from outermost to
+                               next-to-outermost */
+    OFPAT_SET_MPLS_TTL = 15; /* MPLS TTL */
+    OFPAT_DEC_MPLS_TTL = 16; /* Decrement MPLS TTL */
+
+    OFPAT_PUSH_VLAN    = 17; /* Push a new VLAN tag */
+    OFPAT_POP_VLAN     = 18; /* Pop the outer VLAN tag */
+    OFPAT_PUSH_MPLS    = 19; /* Push a new MPLS tag */
+    OFPAT_POP_MPLS     = 20; /* Pop the outer MPLS tag */
+    OFPAT_SET_QUEUE    = 21; /* Set queue id when outputting to a port */
+    OFPAT_GROUP        = 22; /* Apply group. */
+    OFPAT_SET_NW_TTL   = 23; /* IP TTL. */
+    OFPAT_DEC_NW_TTL   = 24; /* Decrement IP TTL. */
+    OFPAT_SET_FIELD    = 25; /* Set a header field using OXM TLV format. */
+    OFPAT_PUSH_PBB     = 26; /* Push a new PBB service tag (I-TAG) */
+    OFPAT_POP_PBB      = 27; /* Pop the outer PBB service tag (I-TAG) */
+    OFPAT_EXPERIMENTER = 0xffff;
+};
+
+/* Action header that is common to all actions.  The length includes the
+ * header and any padding used to make the action 64-bit aligned.
+ * NB: The length of an action *must* always be a multiple of eight. */
+message ofp_action {
+    ofp_action_type type = 1;       /* One of OFPAT_*. */
+    oneof action {
+        ofp_action_output output = 2;
+        ofp_action_mpls_ttl mpls_ttl = 3;
+        ofp_action_push push = 4;
+        ofp_action_pop_mpls pop_mpls = 5;
+        ofp_action_group group = 6;
+        ofp_action_nw_ttl nw_ttl = 7;
+        ofp_action_set_field set_field = 8;
+        ofp_action_experimenter experimenter = 9;
+    }
+};
+
+enum ofp_controller_max_len {
+    OFPCML_INVALID   = 0;
+    OFPCML_MAX       = 0xffe5; /* maximum max_len value which can be used
+                                  to request a specific byte length. */
+    OFPCML_NO_BUFFER = 0xffff; /* indicates that no buffering should be
+                                  applied and the whole packet is to be
+                                  sent to the controller. */
+};
+
+/* Action structure for OFPAT_OUTPUT, which sends packets out 'port'.
+ * When the 'port' is the OFPP_CONTROLLER, 'max_len' indicates the max
+ * number of bytes to send.  A 'max_len' of zero means no bytes of the
+ * packet should be sent. A 'max_len' of OFPCML_NO_BUFFER means that
+ * the packet is not buffered and the complete packet is to be sent to
+ * the controller. */
+message ofp_action_output {
+    uint32 port = 1;                 /* Output port. */
+    uint32 max_len = 2;              /* Max length to send to controller. */
+};
+
+/* Action structure for OFPAT_SET_MPLS_TTL. */
+message ofp_action_mpls_ttl {
+    uint32 mpls_ttl = 1;             /* MPLS TTL */
+};
+
+/* Action structure for OFPAT_PUSH_VLAN/MPLS/PBB. */
+message ofp_action_push {
+    uint32 ethertype = 1;            /* Ethertype */
+};
+
+/* Action structure for OFPAT_POP_MPLS. */
+message ofp_action_pop_mpls {
+    uint32 ethertype = 1;            /* Ethertype */
+};
+
+/* Action structure for OFPAT_GROUP. */
+message ofp_action_group {
+    uint32 group_id = 1;             /* Group identifier. */
+};
+
+/* Action structure for OFPAT_SET_NW_TTL. */
+message ofp_action_nw_ttl {
+    uint32 nw_ttl = 1;               /* IP TTL */
+};
+
+/* Action structure for OFPAT_SET_FIELD. */
+message ofp_action_set_field {
+    ofp_oxm_field field = 1;
+};
+
+/* Action header for OFPAT_EXPERIMENTER.
+ * The rest of the body is experimenter-defined. */
+message ofp_action_experimenter {
+    uint32 experimenter = 1;         /* Experimenter ID which takes the same
+                                        form as in struct
+                                        ofp_experimenter_header. */
+    bytes data = 2;
+};
+
+/* ## ---------------------- ## */
+/* ## OpenFlow Instructions. ## */
+/* ## ---------------------- ## */
+
+enum ofp_instruction_type {
+    OFPIT_INVALID    = 0;
+    OFPIT_GOTO_TABLE = 1;       /* Setup the next table in the lookup
+                                   pipeline */
+    OFPIT_WRITE_METADATA = 2;   /* Setup the metadata field for use later in
+                                   pipeline */
+    OFPIT_WRITE_ACTIONS = 3;    /* Write the action(s) onto the datapath action
+                                   set */
+    OFPIT_APPLY_ACTIONS = 4;    /* Applies the action(s) immediately */
+    OFPIT_CLEAR_ACTIONS = 5;    /* Clears all actions from the datapath
+                                   action set */
+    OFPIT_METER = 6;            /* Apply meter (rate limiter) */
+
+    OFPIT_EXPERIMENTER = 0xFFFF; /* Experimenter instruction */
+};
+
+/* Instruction header that is common to all instructions.  The length includes
+ * the header and any padding used to make the instruction 64-bit aligned.
+ * NB: The length of an instruction *must* always be a multiple of eight. */
+message ofp_instruction {
+    uint32 type = 1;               /* Instruction type */
+    oneof data {
+        ofp_instruction_goto_table goto_table = 2;
+        ofp_instruction_write_metadata write_metadata = 3;
+        ofp_instruction_actions actions = 4;
+        ofp_instruction_meter meter = 5;
+        ofp_instruction_experimenter experimenter = 6;
+    }
+};
+
+/* Instruction structure for OFPIT_GOTO_TABLE */
+message ofp_instruction_goto_table {
+    uint32 table_id = 1;           /* Set next table in the lookup pipeline */
+};
+
+/* Instruction structure for OFPIT_WRITE_METADATA */
+message ofp_instruction_write_metadata {
+    uint64 metadata = 1;           /* Metadata value to write */
+    uint64 metadata_mask = 2;      /* Metadata write bitmask */
+};
+
+/* Instruction structure for OFPIT_WRITE/APPLY/CLEAR_ACTIONS */
+message ofp_instruction_actions {
+    repeated ofp_action actions = 1; /* 0 or more actions associated
+                                        with OFPIT_WRITE_ACTIONS and
+                                        OFPIT_APPLY_ACTIONS */
+};
+
+/* Instruction structure for OFPIT_METER */
+message ofp_instruction_meter {
+    uint32 meter_id = 1;           /* Meter instance. */
+};
+
+/* Instruction structure for experimental instructions */
+message ofp_instruction_experimenter {
+    uint32 experimenter = 1;     /* Experimenter ID which takes the same form
+                                   as in struct ofp_experimenter_header. */
+    /* Experimenter-defined arbitrary additional data. */
+    bytes data = 2;
+};
+
+/* ## --------------------------- ## */
+/* ## OpenFlow Flow Modification. ## */
+/* ## --------------------------- ## */
+
+enum ofp_flow_mod_command {
+    OFPFC_ADD           = 0; /* New flow. */
+    OFPFC_MODIFY        = 1; /* Modify all matching flows. */
+    OFPFC_MODIFY_STRICT = 2; /* Modify entry strictly matching wildcards and
+                                priority. */
+    OFPFC_DELETE        = 3; /* Delete all matching flows. */
+    OFPFC_DELETE_STRICT = 4; /* Delete entry strictly matching wildcards and
+                                priority. */
+};
+
+/* Value used in "idle_timeout" and "hard_timeout" to indicate that the entry
+ * is permanent. */
+//#define OFP_FLOW_PERMANENT 0
+
+/* By default, choose a priority in the middle. */
+//#define OFP_DEFAULT_PRIORITY 0x8000
+
+enum ofp_flow_mod_flags {
+    OFPFF_INVALID       = 0;
+    OFPFF_SEND_FLOW_REM = 1;  /* Send flow removed message when flow
+                               * expires or is deleted. */
+    OFPFF_CHECK_OVERLAP = 2;  /* Check for overlapping entries first. */
+    OFPFF_RESET_COUNTS  = 4;  /* Reset flow packet and byte counts. */
+    OFPFF_NO_PKT_COUNTS = 8;  /* Don't keep track of packet count. */
+    OFPFF_NO_BYT_COUNTS = 16; /* Don't keep track of byte count. */
+};
+
+/* Flow setup and teardown (controller -> datapath). */
+message ofp_flow_mod {
+    //ofp_header header;
+    uint64 cookie = 1;             /* Opaque controller-issued identifier. */
+    uint64 cookie_mask = 2;        /* Mask used to restrict the cookie bits
+                                      that must match when the command is
+                                      OFPFC_MODIFY* or OFPFC_DELETE*. A value
+                                      of 0 indicates no restriction. */
+    uint32 table_id = 3;           /* ID of the table to put the flow in.
+                                      For OFPFC_DELETE_* commands, OFPTT_ALL
+                                      can also be used to delete matching
+                                      flows from all tables. */
+    ofp_flow_mod_command command = 4; /* One of OFPFC_*. */
+    uint32 idle_timeout = 5;       /* Idle time before discarding (seconds). */
+    uint32 hard_timeout = 6;       /* Max time before discarding (seconds). */
+    uint32 priority = 7;           /* Priority level of flow entry. */
+    uint32 buffer_id = 8;          /* Buffered packet to apply to, or
+                                      OFP_NO_BUFFER.
+                                      Not meaningful for OFPFC_DELETE*. */
+    uint32 out_port = 9;          /* For OFPFC_DELETE* commands, require
+                                      matching entries to include this as an
+                                      output port.  A value of OFPP_ANY
+                                      indicates no restriction. */
+    uint32 out_group = 10;         /* For OFPFC_DELETE* commands, require
+                                      matching entries to include this as an
+                                      output group.  A value of OFPG_ANY
+                                      indicates no restriction. */
+    uint32 flags = 11;             /* Bitmap of OFPFF_* flags. */
+    ofp_match match = 12;          /* Fields to match. Variable size. */
+    repeated ofp_instruction instructions = 13; /* 0 or more. */
+};
+
+/* Group numbering. Groups can use any number up to OFPG_MAX. */
+enum ofp_group {
+
+    OFPG_INVALID = 0;
+
+    /* Last usable group number. */
+    OFPG_MAX        = 0x7fffff00;
+
+    /* Fake groups. */
+    OFPG_ALL        = 0x7ffffffc;  /* Represents all groups for group delete
+                                      commands. */
+    OFPG_ANY        = 0x7fffffff;  /* Special wildcard: no group specified. */
+};
+
+/* Group commands */
+enum ofp_group_mod_command {
+    OFPGC_ADD    = 0;       /* New group. */
+    OFPGC_MODIFY = 1;       /* Modify all matching groups. */
+    OFPGC_DELETE = 2;       /* Delete all matching groups. */
+};
+
+/* Bucket for use in groups. */
+message ofp_bucket {
+    uint32 weight = 1;              /* Relative weight of bucket.  Only
+                                       defined for select groups. */
+    uint32 watch_port = 2;          /* Port whose state affects whether this
+                                       bucket is live.  Only required for fast
+                                       failover groups. */
+    uint32 watch_group = 3;         /* Group whose state affects whether this
+                                       bucket is live.  Only required for fast
+                                       failover groups. */
+    repeated ofp_action actions = 4;
+};
+
+/* Group setup and teardown (controller -> datapath). */
+message ofp_group_mod {
+    //ofp_header header;
+    ofp_group_mod_command command = 1; /* One of OFPGC_*. */
+    ofp_group_type type = 2;           /* One of OFPGT_*. */
+    uint32 group_id = 3;               /* Group identifier. */
+    repeated ofp_bucket buckets = 4;
+};
+
+/* Group types.  Values in the range [128; 255] are reserved for experimental
+ * use. */
+enum ofp_group_type {
+    OFPGT_ALL      = 0; /* All (multicast/broadcast) group.  */
+    OFPGT_SELECT   = 1; /* Select group. */
+    OFPGT_INDIRECT = 2; /* Indirect group. */
+    OFPGT_FF       = 3; /* Fast failover group. */
+};
+
+/* Special buffer-id to indicate 'no buffer' */
+//#define OFP_NO_BUFFER 0xffffffff
+
+/* Send packet (controller -> datapath). */
+message ofp_packet_out {
+    //ofp_header header;
+    uint32 buffer_id = 1;          /* ID assigned by datapath (OFP_NO_BUFFER
+                                      if none). */
+    uint32 in_port = 2;            /* Packet's input port or OFPP_CONTROLLER.*/
+    repeated ofp_action actions = 3; /* Action list - 0 or more. */
+    /* The variable size action list is optionally followed by packet data.
+     * This data is only present and meaningful if buffer_id == -1. */
+    bytes data = 4;                /* Packet data. */
+};
+
+/* Why is this packet being sent to the controller? */
+enum ofp_packet_in_reason {
+    OFPR_NO_MATCH    = 0;   /* No matching flow (table-miss flow entry). */
+    OFPR_ACTION      = 1;   /* Action explicitly output to controller. */
+    OFPR_INVALID_TTL = 2;   /* Packet has invalid TTL */
+};
+
+/* Packet received on port (datapath -> controller). */
+message ofp_packet_in {
+    //ofp_header header;
+    uint32 buffer_id = 1;     /* ID assigned by datapath. */
+    ofp_packet_in_reason reason = 2; /* Reason packet is being sent */
+    uint32 table_id = 3;      /* ID of the table that was looked up */
+    uint64 cookie = 4;        /* Cookie of the flow entry that was looked up. */
+    ofp_match match = 5;      /* Packet metadata. Variable size. */
+    bytes data = 6;           /* Ethernet frame */
+};
+
+/* Why was this flow removed? */
+enum ofp_flow_removed_reason {
+    OFPRR_IDLE_TIMEOUT = 0;     /* Flow idle time exceeded idle_timeout. */
+    OFPRR_HARD_TIMEOUT = 1;     /* Time exceeded hard_timeout. */
+    OFPRR_DELETE       = 2;     /* Evicted by a DELETE flow mod. */
+    OFPRR_GROUP_DELETE = 3;     /* Group was removed. */
+    OFPRR_METER_DELETE = 4;     /* Meter was removed */
+};
+
+/* Flow removed (datapath -> controller). */
+message ofp_flow_removed {
+    //ofp_header header;
+    uint64 cookie = 1;         /* Opaque controller-issued identifier. */
+
+    uint32 priority = 2;       /* Priority level of flow entry. */
+    ofp_flow_removed_reason reason = 3; /* One of OFPRR_*. */
+    uint32 table_id = 4;        /* ID of the table */
+
+    uint32 duration_sec = 5;   /* Time flow was alive in seconds. */
+    uint32 duration_nsec = 6;  /* Time flow was alive in nanoseconds beyond
+                                 duration_sec. */
+    uint32 idle_timeout = 7;   /* Idle timeout from original flow mod. */
+    uint32 hard_timeout = 8;   /* Hard timeout from original flow mod. */
+    uint64 packet_count = 9;
+    uint64 byte_count = 10;
+    ofp_match match = 121;  /* Description of fields. Variable size. */
+};
+
+/* Meter numbering. Flow meters can use any number up to OFPM_MAX. */
+enum ofp_meter {
+    OFPM_ZERO       = 0;
+    /* Last usable meter. */
+    OFPM_MAX        = 0x7fff0000;
+
+    /* Virtual meters. */
+    OFPM_SLOWPATH   = 0x7ffffffd;  /* Meter for slow datapath. */
+    OFPM_CONTROLLER = 0x7ffffffe;  /* Meter for controller connection. */
+    OFPM_ALL        = 0x7fffffff;  /* Represents all meters for stat requests
+                                      commands. */
+};
+
+/* Meter band types */
+enum ofp_meter_band_type {
+    OFPMBT_INVALID         = 0;
+    OFPMBT_DROP            = 1;      /* Drop packet. */
+    OFPMBT_DSCP_REMARK     = 2;      /* Remark DSCP in the IP header. */
+    OFPMBT_EXPERIMENTER    = 0xFFFF; /* Experimenter meter band. */
+};
+
+/* Common header for all meter bands */
+message ofp_meter_band_header {
+    ofp_meter_band_type type = 1;   /* One of OFPMBT_*. */
+    uint32              len = 2;    /* Length in bytes of this band. */
+    uint32              rate = 3;   /* Rate for this band. */
+    uint32              burst_size = 4;/* Size of bursts. */
+};
+
+/* OFPMBT_DROP band - drop packets */
+message ofp_meter_band_drop {
+    uint32        type = 1;   /* OFPMBT_DROP. */
+    uint32        len = 2;   /* Length in bytes of this band. */
+    uint32        rate = 3;   /* Rate for dropping packets. */
+    uint32        burst_size = 4;/* Size of bursts. */
+};
+
+/* OFPMBT_DSCP_REMARK band - Remark DSCP in the IP header */
+message ofp_meter_band_dscp_remark {
+    uint32        type = 1;       /* OFPMBT_DSCP_REMARK. */
+    uint32        len = 2;        /* Length in bytes of this band. */
+    uint32        rate = 3;       /* Rate for remarking packets. */
+    uint32        burst_size = 4; /* Size of bursts. */
+    uint32        prec_level = 5; /* Number of drop precedence level to add. */
+};
+
+/* OFPMBT_EXPERIMENTER band - Experimenter type.
+ * The rest of the band is experimenter-defined. */
+message ofp_meter_band_experimenter {
+    ofp_meter_band_type type = 1;        /* One of OFPMBT_*. */
+    uint32              len = 2;         /* Length in bytes of this band. */
+    uint32              rate = 3;        /* Rate for this band. */
+    uint32              burst_size = 4;  /* Size of bursts. */
+    uint32              experimenter = 5;/* Experimenter ID which takes the
+                                            same form as in struct
+                                            ofp_experimenter_header. */
+};
+
+/* Meter commands */
+enum ofp_meter_mod_command {
+    OFPMC_ADD = 0;              /* New meter. */
+    OFPMC_MODIFY = 1;           /* Modify specified meter. */
+    OFPMC_DELETE = 2;           /* Delete specified meter. */
+};
+
+/* Meter configuration flags */
+enum ofp_meter_flags {
+    OFPMF_INVALID = 0;
+    OFPMF_KBPS    = 1;     /* Rate value in kb/s (kilo-bit per second). */
+    OFPMF_PKTPS   = 2;     /* Rate value in packet/sec. */
+    OFPMF_BURST   = 4;     /* Do burst size. */
+    OFPMF_STATS   = 8;     /* Collect statistics. */
+};
+
+/* Meter configuration. OFPT_METER_MOD. */
+message ofp_meter_mod {
+//    ofp_header   header = 1;
+    ofp_meter_mod_command command = 1;       /* One of OFPMC_*. */
+    uint32                flags = 2;         /* Bitmap of OFPMF_* flags. */
+    uint32                meter_id = 3;      /* Meter instance. */
+    repeated ofp_meter_band_header bands = 4; /* The band list length is
+                                                 inferred from the length field
+                                                 in the header. */
+};
+
+/* Values for 'type' in ofp_error_message.  These values are immutable: they
+ * will not change in future versions of the protocol (although new values may
+ * be added). */
+enum ofp_error_type {
+    OFPET_HELLO_FAILED         = 0;  /* Hello protocol failed. */
+    OFPET_BAD_REQUEST          = 1;  /* Request was not understood. */
+    OFPET_BAD_ACTION           = 2;  /* Error in action description. */
+    OFPET_BAD_INSTRUCTION      = 3;  /* Error in instruction list. */
+    OFPET_BAD_MATCH            = 4;  /* Error in match. */
+    OFPET_FLOW_MOD_FAILED      = 5;  /* Problem modifying flow entry. */
+    OFPET_GROUP_MOD_FAILED     = 6;  /* Problem modifying group entry. */
+    OFPET_PORT_MOD_FAILED      = 7;  /* Port mod request failed. */
+    OFPET_TABLE_MOD_FAILED     = 8;  /* Table mod request failed. */
+    OFPET_QUEUE_OP_FAILED      = 9;  /* Queue operation failed. */
+    OFPET_SWITCH_CONFIG_FAILED = 10; /* Switch config request failed. */
+    OFPET_ROLE_REQUEST_FAILED  = 11; /* Controller Role request failed. */
+    OFPET_METER_MOD_FAILED     = 12; /* Error in meter. */
+    OFPET_TABLE_FEATURES_FAILED = 13; /* Setting table features failed. */
+    OFPET_EXPERIMENTER = 0xffff;      /* Experimenter error messages. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_HELLO_FAILED.  'data' contains an
+ * ASCII text string that may give failure details. */
+enum ofp_hello_failed_code {
+    OFPHFC_INCOMPATIBLE = 0;    /* No compatible version. */
+    OFPHFC_EPERM        = 1;    /* Permissions error. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_BAD_REQUEST.  'data' contains at least
+ * the first 64 bytes of the failed request. */
+enum ofp_bad_request_code {
+    OFPBRC_BAD_VERSION      = 0;  /* ofp_header.version not supported. */
+    OFPBRC_BAD_TYPE         = 1;  /* ofp_header.type not supported. */
+    OFPBRC_BAD_MULTIPART    = 2;  /* ofp_multipart_request.type not supported.
+                                   */
+    OFPBRC_BAD_EXPERIMENTER = 3;  /* Experimenter id not supported
+                                   * (in ofp_experimenter_header or
+                                   * ofp_multipart_request or
+                                   * ofp_multipart_reply). */
+    OFPBRC_BAD_EXP_TYPE     = 4;  /* Experimenter type not supported. */
+    OFPBRC_EPERM            = 5;  /* Permissions error. */
+    OFPBRC_BAD_LEN          = 6;  /* Wrong request length for type. */
+    OFPBRC_BUFFER_EMPTY     = 7;  /* Specified buffer has already been used. */
+    OFPBRC_BUFFER_UNKNOWN   = 8;  /* Specified buffer does not exist. */
+    OFPBRC_BAD_TABLE_ID     = 9;  /* Specified table-id invalid or does not
+                                   * exist. */
+    OFPBRC_IS_SLAVE         = 10; /* Denied because controller is slave. */
+    OFPBRC_BAD_PORT         = 11; /* Invalid port. */
+    OFPBRC_BAD_PACKET       = 12; /* Invalid packet in packet-out. */
+    OFPBRC_MULTIPART_BUFFER_OVERFLOW    = 13; /* ofp_multipart_request
+                                     overflowed the assigned buffer. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_BAD_ACTION.  'data' contains at least
+ * the first 64 bytes of the failed request. */
+enum ofp_bad_action_code {
+    OFPBAC_BAD_TYPE           = 0;  /* Unknown or unsupported action type. */
+    OFPBAC_BAD_LEN            = 1;  /* Length problem in actions. */
+    OFPBAC_BAD_EXPERIMENTER   = 2;  /* Unknown experimenter id specified. */
+    OFPBAC_BAD_EXP_TYPE       = 3;  /* Unknown action for experimenter id. */
+    OFPBAC_BAD_OUT_PORT       = 4;  /* Problem validating output port. */
+    OFPBAC_BAD_ARGUMENT       = 5;  /* Bad action argument. */
+    OFPBAC_EPERM              = 6;  /* Permissions error. */
+    OFPBAC_TOO_MANY           = 7;  /* Can't handle this many actions. */
+    OFPBAC_BAD_QUEUE          = 8;  /* Problem validating output queue. */
+    OFPBAC_BAD_OUT_GROUP      = 9;  /* Invalid group id in forward action. */
+    OFPBAC_MATCH_INCONSISTENT = 10; /* Action can't apply for this match,
+                                       or Set-Field missing prerequisite. */
+    OFPBAC_UNSUPPORTED_ORDER  = 11; /* Action order is unsupported for the
+                                 action list in an Apply-Actions instruction */
+    OFPBAC_BAD_TAG            = 12; /* Actions uses an unsupported
+                                       tag/encap. */
+    OFPBAC_BAD_SET_TYPE       = 13; /* Unsupported type in SET_FIELD action. */
+    OFPBAC_BAD_SET_LEN        = 14; /* Length problem in SET_FIELD action. */
+    OFPBAC_BAD_SET_ARGUMENT   = 15; /* Bad argument in SET_FIELD action. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_BAD_INSTRUCTION.  'data' contains at
+ * least the first 64 bytes of the failed request. */
+enum ofp_bad_instruction_code {
+    OFPBIC_UNKNOWN_INST     = 0; /* Unknown instruction. */
+    OFPBIC_UNSUP_INST       = 1; /* Switch or table does not support the
+                                    instruction. */
+    OFPBIC_BAD_TABLE_ID     = 2; /* Invalid Table-ID specified. */
+    OFPBIC_UNSUP_METADATA   = 3; /* Metadata value unsupported by datapath. */
+    OFPBIC_UNSUP_METADATA_MASK = 4; /* Metadata mask value unsupported by
+                                       datapath. */
+    OFPBIC_BAD_EXPERIMENTER = 5; /* Unknown experimenter id specified. */
+    OFPBIC_BAD_EXP_TYPE     = 6; /* Unknown instruction for experimenter id. */
+    OFPBIC_BAD_LEN          = 7; /* Length problem in instructions. */
+    OFPBIC_EPERM            = 8; /* Permissions error. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_BAD_MATCH.  'data' contains at least
+ * the first 64 bytes of the failed request. */
+enum ofp_bad_match_code {
+    OFPBMC_BAD_TYPE         = 0;  /* Unsupported match type specified by the
+                                     match */
+    OFPBMC_BAD_LEN          = 1;  /* Length problem in match. */
+    OFPBMC_BAD_TAG          = 2;  /* Match uses an unsupported tag/encap. */
+    OFPBMC_BAD_DL_ADDR_MASK = 3;  /* Unsupported datalink addr mask - switch
+                                     does not support arbitrary datalink
+                                     address mask. */
+    OFPBMC_BAD_NW_ADDR_MASK = 4;  /* Unsupported network addr mask - switch
+                                     does not support arbitrary network
+                                     address mask. */
+    OFPBMC_BAD_WILDCARDS    = 5;  /* Unsupported combination of fields masked
+                                     or omitted in the match. */
+    OFPBMC_BAD_FIELD        = 6;  /* Unsupported field type in the match. */
+    OFPBMC_BAD_VALUE        = 7;  /* Unsupported value in a match field. */
+    OFPBMC_BAD_MASK         = 8;  /* Unsupported mask specified in the match,
+                                     field is not dl-address or nw-address. */
+    OFPBMC_BAD_PREREQ       = 9;  /* A prerequisite was not met. */
+    OFPBMC_DUP_FIELD        = 10; /* A field type was duplicated. */
+    OFPBMC_EPERM            = 11; /* Permissions error. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_FLOW_MOD_FAILED.  'data' contains
+ * at least the first 64 bytes of the failed request. */
+enum ofp_flow_mod_failed_code {
+    OFPFMFC_UNKNOWN      = 0;   /* Unspecified error. */
+    OFPFMFC_TABLE_FULL   = 1;   /* Flow not added because table was full. */
+    OFPFMFC_BAD_TABLE_ID = 2;   /* Table does not exist */
+    OFPFMFC_OVERLAP      = 3;   /* Attempted to add overlapping flow with
+                                   CHECK_OVERLAP flag set. */
+    OFPFMFC_EPERM        = 4;   /* Permissions error. */
+    OFPFMFC_BAD_TIMEOUT  = 5;   /* Flow not added because of unsupported
+                                   idle/hard timeout. */
+    OFPFMFC_BAD_COMMAND  = 6;   /* Unsupported or unknown command. */
+    OFPFMFC_BAD_FLAGS    = 7;   /* Unsupported or unknown flags. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_GROUP_MOD_FAILED.  'data' contains
+ * at least the first 64 bytes of the failed request. */
+enum ofp_group_mod_failed_code {
+    OFPGMFC_GROUP_EXISTS         = 0;  /* Group not added because a group ADD
+                                          attempted to replace an
+                                          already-present group. */
+    OFPGMFC_INVALID_GROUP        = 1;  /* Group not added because Group
+                                          specified is invalid. */
+    OFPGMFC_WEIGHT_UNSUPPORTED   = 2;  /* Switch does not support unequal load
+                                          sharing with select groups. */
+    OFPGMFC_OUT_OF_GROUPS        = 3;  /* The group table is full. */
+    OFPGMFC_OUT_OF_BUCKETS       = 4;  /* The maximum number of action buckets
+                                          for a group has been exceeded. */
+    OFPGMFC_CHAINING_UNSUPPORTED = 5;  /* Switch does not support groups that
+                                          forward to groups. */
+    OFPGMFC_WATCH_UNSUPPORTED    = 6;  /* This group cannot watch the
+                                          watch_port or watch_group specified.
+                                        */
+    OFPGMFC_LOOP                 = 7;  /* Group entry would cause a loop. */
+    OFPGMFC_UNKNOWN_GROUP        = 8;  /* Group not modified because a group
+                                          MODIFY attempted to modify a
+                                          non-existent group. */
+    OFPGMFC_CHAINED_GROUP        = 9;  /* Group not deleted because another
+                                          group is forwarding to it. */
+    OFPGMFC_BAD_TYPE             = 10; /* Unsupported or unknown group type. */
+    OFPGMFC_BAD_COMMAND          = 11; /* Unsupported or unknown command. */
+    OFPGMFC_BAD_BUCKET           = 12; /* Error in bucket. */
+    OFPGMFC_BAD_WATCH            = 13; /* Error in watch port/group. */
+    OFPGMFC_EPERM                = 14; /* Permissions error. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_PORT_MOD_FAILED.  'data' contains
+ * at least the first 64 bytes of the failed request. */
+enum ofp_port_mod_failed_code {
+    OFPPMFC_BAD_PORT      = 0;   /* Specified port number does not exist. */
+    OFPPMFC_BAD_HW_ADDR   = 1;   /* Specified hardware address does not
+                                  * match the port number. */
+    OFPPMFC_BAD_CONFIG    = 2;   /* Specified config is invalid. */
+    OFPPMFC_BAD_ADVERTISE = 3;   /* Specified advertise is invalid. */
+    OFPPMFC_EPERM         = 4;   /* Permissions error. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_TABLE_MOD_FAILED.  'data' contains
+ * at least the first 64 bytes of the failed request. */
+enum ofp_table_mod_failed_code {
+    OFPTMFC_BAD_TABLE  = 0;      /* Specified table does not exist. */
+    OFPTMFC_BAD_CONFIG = 1;      /* Specified config is invalid. */
+    OFPTMFC_EPERM      = 2;      /* Permissions error. */
+};
+
+/* ofp_error msg 'code' values for OFPET_QUEUE_OP_FAILED. 'data' contains
+ * at least the first 64 bytes of the failed request */
+enum ofp_queue_op_failed_code {
+    OFPQOFC_BAD_PORT   = 0;     /* Invalid port (or port does not exist). */
+    OFPQOFC_BAD_QUEUE  = 1;     /* Queue does not exist. */
+    OFPQOFC_EPERM      = 2;     /* Permissions error. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_SWITCH_CONFIG_FAILED. 'data' contains
+ * at least the first 64 bytes of the failed request. */
+enum ofp_switch_config_failed_code {
+    OFPSCFC_BAD_FLAGS  = 0;      /* Specified flags is invalid. */
+    OFPSCFC_BAD_LEN    = 1;      /* Specified len is invalid. */
+    OFPSCFC_EPERM      = 2;      /* Permissions error. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_ROLE_REQUEST_FAILED. 'data' contains
+ * at least the first 64 bytes of the failed request. */
+enum ofp_role_request_failed_code {
+    OFPRRFC_STALE      = 0;      /* Stale Message: old generation_id. */
+    OFPRRFC_UNSUP      = 1;      /* Controller role change unsupported. */
+    OFPRRFC_BAD_ROLE   = 2;      /* Invalid role. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_METER_MOD_FAILED.  'data' contains
+ * at least the first 64 bytes of the failed request. */
+enum ofp_meter_mod_failed_code {
+    OFPMMFC_UNKNOWN       = 0;  /* Unspecified error. */
+    OFPMMFC_METER_EXISTS  = 1;  /* Meter not added because a Meter ADD
+                                 * attempted to replace an existing Meter. */
+    OFPMMFC_INVALID_METER = 2;  /* Meter not added because Meter specified
+                                 * is invalid,
+                                 * or invalid meter in meter action. */
+    OFPMMFC_UNKNOWN_METER = 3;  /* Meter not modified because a Meter MODIFY
+                                 * attempted to modify a non-existent Meter,
+                                 * or bad meter in meter action. */
+    OFPMMFC_BAD_COMMAND   = 4;  /* Unsupported or unknown command. */
+    OFPMMFC_BAD_FLAGS     = 5;  /* Flag configuration unsupported. */
+    OFPMMFC_BAD_RATE      = 6;  /* Rate unsupported. */
+    OFPMMFC_BAD_BURST     = 7;  /* Burst size unsupported. */
+    OFPMMFC_BAD_BAND      = 8;  /* Band unsupported. */
+    OFPMMFC_BAD_BAND_VALUE = 9; /* Band value unsupported. */
+    OFPMMFC_OUT_OF_METERS = 10; /* No more meters available. */
+    OFPMMFC_OUT_OF_BANDS  = 11; /* The maximum number of properties
+                                 * for a meter has been exceeded. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_TABLE_FEATURES_FAILED. 'data' contains
+ * at least the first 64 bytes of the failed request. */
+enum ofp_table_features_failed_code {
+    OFPTFFC_BAD_TABLE    = 0;      /* Specified table does not exist. */
+    OFPTFFC_BAD_METADATA = 1;      /* Invalid metadata mask. */
+    OFPTFFC_BAD_TYPE     = 2;      /* Unknown property type. */
+    OFPTFFC_BAD_LEN      = 3;      /* Length problem in properties. */
+    OFPTFFC_BAD_ARGUMENT = 4;      /* Unsupported property value. */
+    OFPTFFC_EPERM        = 5;      /* Permissions error. */
+};
+
+/* OFPT_ERROR: Error message (datapath -> controller). */
+message ofp_error_msg {
+    //ofp_header header;
+    uint32 type = 1;
+    uint32 code = 2;
+    bytes data = 3;          /* Variable-length data.  Interpreted based
+                                 on the type and code.  No padding. */
+};
+
+/* OFPET_EXPERIMENTER: Error message (datapath -> controller). */
+message ofp_error_experimenter_msg {
+    //ofp_header header;
+
+    uint32 type = 1;           /* OFPET_EXPERIMENTER. */
+    uint32 exp_type = 2;       /* Experimenter defined. */
+    uint32 experimenter = 3;   /* Experimenter ID which takes the same form
+                                    as in struct ofp_experimenter_header. */
+    bytes data = 4;              /* Variable-length data.  Interpreted based
+                                    on the type and code.  No padding. */
+};
+
+enum ofp_multipart_type {
+    /* Description of this OpenFlow switch.
+     * The request body is empty.
+     * The reply body is struct ofp_desc. */
+    OFPMP_DESC = 0;
+
+    /* Individual flow statistics.
+     * The request body is struct ofp_flow_stats_request.
+     * The reply body is an array of struct ofp_flow_stats. */
+    OFPMP_FLOW = 1;
+
+    /* Aggregate flow statistics.
+     * The request body is struct ofp_aggregate_stats_request.
+     * The reply body is struct ofp_aggregate_stats_reply. */
+    OFPMP_AGGREGATE = 2;
+
+    /* Flow table statistics.
+     * The request body is empty.
+     * The reply body is an array of struct ofp_table_stats. */
+    OFPMP_TABLE = 3;
+
+    /* Port statistics.
+     * The request body is struct ofp_port_stats_request.
+     * The reply body is an array of struct ofp_port_stats. */
+    OFPMP_PORT_STATS = 4;
+
+    /* Queue statistics for a port
+     * The request body is struct ofp_queue_stats_request.
+     * The reply body is an array of struct ofp_queue_stats */
+    OFPMP_QUEUE = 5;
+
+    /* Group counter statistics.
+     * The request body is struct ofp_group_stats_request.
+     * The reply is an array of struct ofp_group_stats. */
+    OFPMP_GROUP = 6;
+
+    /* Group description.
+     * The request body is empty.
+     * The reply body is an array of struct ofp_group_desc. */
+    OFPMP_GROUP_DESC = 7;
+
+    /* Group features.
+     * The request body is empty.
+     * The reply body is struct ofp_group_features. */
+    OFPMP_GROUP_FEATURES = 8;
+
+    /* Meter statistics.
+     * The request body is struct ofp_meter_multipart_requests.
+     * The reply body is an array of struct ofp_meter_stats. */
+    OFPMP_METER = 9;
+
+    /* Meter configuration.
+     * The request body is struct ofp_meter_multipart_requests.
+     * The reply body is an array of struct ofp_meter_config. */
+    OFPMP_METER_CONFIG = 10;
+
+    /* Meter features.
+     * The request body is empty.
+     * The reply body is struct ofp_meter_features. */
+    OFPMP_METER_FEATURES = 11;
+
+    /* Table features.
+     * The request body is either empty or contains an array of
+     * struct ofp_table_features containing the controller's
+     * desired view of the switch. If the switch is unable to
+     * set the specified view an error is returned.
+     * The reply body is an array of struct ofp_table_features. */
+    OFPMP_TABLE_FEATURES = 12;
+
+    /* Port description.
+     * The request body is empty.
+     * The reply body is an array of struct ofp_port. */
+    OFPMP_PORT_DESC = 13;
+
+    /* Experimenter extension.
+     * The request and reply bodies begin with
+     * struct ofp_experimenter_multipart_header.
+     * The request and reply bodies are otherwise experimenter-defined. */
+    OFPMP_EXPERIMENTER = 0xffff;
+};
+
+/* Backward compatibility with 1.3.1 - avoid breaking the API. */
+//#define ofp_multipart_types ofp_multipart_type
+
+enum ofp_multipart_request_flags {
+    OFPMPF_REQ_INVALID = 0;
+    OFPMPF_REQ_MORE  = 1;  /* More requests to follow. */
+};
+
+message ofp_multipart_request {
+    //ofp_header header;
+    ofp_multipart_type type = 1; /* One of the OFPMP_* constants. */
+    uint32 flags = 2;            /* OFPMPF_REQ_* flags. */
+    bytes body = 3;              /* Body of the request. 0 or more bytes. */
+};
+
+enum ofp_multipart_reply_flags {
+    OFPMPF_REPLY_INVALID = 0;
+    OFPMPF_REPLY_MORE  = 1;  /* More replies to follow. */
+};
+
+message ofp_multipart_reply {
+    //ofp_header header;
+    ofp_multipart_type type = 1; /* One of the OFPMP_* constants. */
+    uint32 flags = 2;            /* OFPMPF_REPLY_* flags. */
+    bytes body = 3;              /* Body of the reply. 0 or more bytes. */
+};
+
+//#define DESC_STR_LEN   256
+//#define SERIAL_NUM_LEN 32
+/* Body of reply to OFPMP_DESC request.  Each entry is a NULL-terminated
+ * ASCII string. */
+message ofp_desc {
+    string mfr_desc = 1;       /* Manufacturer description. */
+    string hw_desc = 2;        /* Hardware description. */
+    string sw_desc = 3;        /* Software description. */
+    string serial_num = 4;     /* Serial number. */
+    string dp_desc = 5;        /* Human readable description of datapath. */
+};
+
+/* Body for ofp_multipart_request of type OFPMP_FLOW. */
+message ofp_flow_stats_request {
+    uint32 table_id = 1;       /* ID of table to read (from ofp_table_stats),
+                                    OFPTT_ALL for all tables. */
+    uint32 out_port = 2;       /* Require matching entries to include this
+                                    as an output port.  A value of OFPP_ANY
+                                    indicates no restriction. */
+    uint32 out_group = 3;      /* Require matching entries to include this
+                                    as an output group.  A value of OFPG_ANY
+                                    indicates no restriction. */
+    uint64 cookie = 4;         /* Require matching entries to contain this
+                                    cookie value */
+    uint64 cookie_mask = 5;    /* Mask used to restrict the cookie bits that
+                                    must match. A value of 0 indicates
+                                    no restriction. */
+    ofp_match match = 6;         /* Fields to match. Variable size. */
+};
+
+/* Body of reply to OFPMP_FLOW request. */
+message ofp_flow_stats {
+    uint64 id = 14;            /* Unique ID of flow within device. */
+    uint32 table_id = 1;       /* ID of table flow came from. */
+    uint32 duration_sec = 2;   /* Time flow has been alive in seconds. */
+    uint32 duration_nsec = 3;  /* Time flow has been alive in nanoseconds
+                                  beyond duration_sec. */
+    uint32 priority = 4;       /* Priority of the entry. */
+    uint32 idle_timeout = 5;   /* Number of seconds idle before expiration. */
+    uint32 hard_timeout = 6;   /* Number of seconds before expiration. */
+    uint32 flags = 7;          /* Bitmap of OFPFF_* flags. */
+    uint64 cookie = 8;         /* Opaque controller-issued identifier. */
+    uint64 packet_count = 9;   /* Number of packets in flow. */
+    uint64 byte_count = 10;    /* Number of bytes in flow. */
+    ofp_match match = 12;      /* Description of fields. Variable size. */
+    repeated ofp_instruction instructions = 13; /* Instruction set
+                                                   (0 or more) */
+};
+
+/* Body for ofp_multipart_request of type OFPMP_AGGREGATE. */
+message ofp_aggregate_stats_request {
+    uint32 table_id = 1;      /* ID of table to read (from ofp_table_stats)
+                                 OFPTT_ALL for all tables. */
+    uint32 out_port = 2;      /* Require matching entries to include this
+                                 as an output port.  A value of OFPP_ANY
+                                 indicates no restriction. */
+    uint32 out_group = 3;     /* Require matching entries to include this
+                                 as an output group.  A value of OFPG_ANY
+                                 indicates no restriction. */
+    uint64 cookie = 4;        /* Require matching entries to contain this
+                                 cookie value */
+    uint64 cookie_mask = 5;   /* Mask used to restrict the cookie bits that
+                                 must match. A value of 0 indicates
+                                 no restriction. */
+    ofp_match match = 6;      /* Fields to match. Variable size. */
+};
+
+/* Body of reply to OFPMP_AGGREGATE request. */
+message ofp_aggregate_stats_reply {
+    uint64 packet_count = 1;   /* Number of packets in flows. */
+    uint64 byte_count = 2;     /* Number of bytes in flows. */
+    uint32 flow_count = 3;     /* Number of flows. */
+};
+
+/* Table Feature property types.
+ * Low order bit cleared indicates a property for a regular Flow Entry.
+ * Low order bit set indicates a property for the Table-Miss Flow Entry.
+ */
+enum ofp_table_feature_prop_type {
+    OFPTFPT_INSTRUCTIONS           = 0;  /* Instructions property. */
+    OFPTFPT_INSTRUCTIONS_MISS      = 1;  /* Instructions for table-miss. */
+    OFPTFPT_NEXT_TABLES            = 2;  /* Next Table property. */
+    OFPTFPT_NEXT_TABLES_MISS       = 3;  /* Next Table for table-miss. */
+    OFPTFPT_WRITE_ACTIONS          = 4;  /* Write Actions property. */
+    OFPTFPT_WRITE_ACTIONS_MISS     = 5;  /* Write Actions for table-miss. */
+    OFPTFPT_APPLY_ACTIONS          = 6;  /* Apply Actions property. */
+    OFPTFPT_APPLY_ACTIONS_MISS     = 7;  /* Apply Actions for table-miss. */
+    OFPTFPT_MATCH                  = 8;  /* Match property. */
+    OFPTFPT_WILDCARDS              = 10; /* Wildcards property. */
+    OFPTFPT_WRITE_SETFIELD         = 12; /* Write Set-Field property. */
+    OFPTFPT_WRITE_SETFIELD_MISS    = 13; /* Write Set-Field for table-miss. */
+    OFPTFPT_APPLY_SETFIELD         = 14; /* Apply Set-Field property. */
+    OFPTFPT_APPLY_SETFIELD_MISS    = 15; /* Apply Set-Field for table-miss. */
+    OFPTFPT_EXPERIMENTER           = 0xFFFE; /* Experimenter property. */
+    OFPTFPT_EXPERIMENTER_MISS      = 0xFFFF; /* Experimenter for table-miss. */
+};
+
+/* Common header for all Table Feature Properties */
+message ofp_table_feature_property {
+    ofp_table_feature_prop_type type = 1;   /* One of OFPTFPT_*. */
+    oneof value {
+        ofp_table_feature_prop_instructions instructions = 2;
+        ofp_table_feature_prop_next_tables next_tables = 3;
+        ofp_table_feature_prop_actions actions = 4;
+        ofp_table_feature_prop_oxm oxm = 5;
+        ofp_table_feature_prop_experimenter experimenter = 6;
+    }
+};
+
+/* Instructions property */
+message ofp_table_feature_prop_instructions {
+    /* One of OFPTFPT_INSTRUCTIONS,
+       OFPTFPT_INSTRUCTIONS_MISS. */
+    repeated ofp_instruction instructions = 1;   /* List of instructions */
+};
+
+/* Next Tables property */
+message ofp_table_feature_prop_next_tables {
+    /* One of OFPTFPT_NEXT_TABLES,
+       OFPTFPT_NEXT_TABLES_MISS. */
+    repeated uint32 next_table_ids = 1;     /* List of table ids. */
+};
+
+/* Actions property */
+message ofp_table_feature_prop_actions {
+    /* One of OFPTFPT_WRITE_ACTIONS,
+       OFPTFPT_WRITE_ACTIONS_MISS,
+       OFPTFPT_APPLY_ACTIONS,
+       OFPTFPT_APPLY_ACTIONS_MISS. */
+    repeated ofp_action actions = 1; /* List of actions */
+};
+
+/* Match, Wildcard or Set-Field property */
+message ofp_table_feature_prop_oxm {
+    /* One of OFPTFPT_MATCH,
+       OFPTFPT_WILDCARDS,
+       OFPTFPT_WRITE_SETFIELD,
+       OFPTFPT_WRITE_SETFIELD_MISS,
+       OFPTFPT_APPLY_SETFIELD,
+       OFPTFPT_APPLY_SETFIELD_MISS. */
+    /* TODO is this a uint32??? */
+    repeated uint32 oxm_ids = 3;    /* Array of OXM headers */
+};
+
+/* Experimenter table feature property */
+message ofp_table_feature_prop_experimenter {
+    /* One of OFPTFPT_EXPERIMENTER,
+       OFPTFPT_EXPERIMENTER_MISS. */
+    uint32         experimenter = 2; /* Experimenter ID which takes the same
+                                        form as in struct
+                                        ofp_experimenter_header. */
+    uint32         exp_type = 3;      /* Experimenter defined. */
+    repeated uint32 experimenter_data = 4;
+};
+
+/* Body for ofp_multipart_request of type OFPMP_TABLE_FEATURES./
+ * Body of reply to OFPMP_TABLE_FEATURES request. */
+message ofp_table_features {
+    uint32 table_id = 1;       /* Identifier of table.  Lower numbered tables
+                                are consulted first. */
+    string name = 2;
+    uint64 metadata_match = 3; /* Bits of metadata table can match. */
+    uint64 metadata_write = 4; /* Bits of metadata table can write. */
+    uint32 config = 5;         /* Bitmap of OFPTC_* values */
+    uint32 max_entries = 6;    /* Max number of entries supported. */
+
+    /* Table Feature Property list */
+    repeated ofp_table_feature_property properties = 7;
+};
+
+/* Body of reply to OFPMP_TABLE request. */
+message ofp_table_stats {
+    uint32 table_id = 1;      /* Identifier of table.  Lower numbered tables
+                                 are consulted first. */
+    uint32 active_count = 2;  /* Number of active entries. */
+    uint64 lookup_count = 3;  /* Number of packets looked up in table. */
+    uint64 matched_count = 4; /* Number of packets that hit table. */
+};
+
+/* Body for ofp_multipart_request of type OFPMP_PORT. */
+message ofp_port_stats_request {
+    uint32 port_no = 1;       /* OFPMP_PORT message must request statistics
+                               * either for a single port (specified in
+                               * port_no) or for all ports (if port_no ==
+                               * OFPP_ANY). */
+};
+
+/* Body of reply to OFPMP_PORT request. If a counter is unsupported, set
+ * the field to all ones. */
+message ofp_port_stats {
+    uint32 port_no = 1;
+    uint64 rx_packets = 2;   /* Number of received packets. */
+    uint64 tx_packets = 3;   /* Number of transmitted packets. */
+    uint64 rx_bytes = 4;     /* Number of received bytes. */
+    uint64 tx_bytes = 5;     /* Number of transmitted bytes. */
+    uint64 rx_dropped = 6;   /* Number of packets dropped by RX. */
+    uint64 tx_dropped = 7;   /* Number of packets dropped by TX. */
+    uint64 rx_errors = 8;    /* Number of receive errors.  This is a super-set
+                                of more specific receive errors and should be
+                                greater than or equal to the sum of all
+                                rx_*_err values. */
+    uint64 tx_errors = 9;    /* Number of transmit errors.  This is a super-set
+                                of more specific transmit errors and should be
+                                greater than or equal to the sum of all
+                                tx_*_err values (none currently defined.) */
+    uint64 rx_frame_err = 10;  /* Number of frame alignment errors. */
+    uint64 rx_over_err = 11;   /* Number of packets with RX overrun. */
+    uint64 rx_crc_err = 12;    /* Number of CRC errors. */
+    uint64 collisions = 13;    /* Number of collisions. */
+    uint32 duration_sec = 14;  /* Time port has been alive in seconds. */
+    uint32 duration_nsec = 15; /* Time port has been alive in nanoseconds
+                                  beyond duration_sec. */
+};
+
+/* Body of OFPMP_GROUP request. */
+message ofp_group_stats_request {
+    uint32 group_id = 1;      /* All groups if OFPG_ALL. */
+};
+
+/* Used in group stats replies. */
+message ofp_bucket_counter {
+    uint64 packet_count = 1;  /* Number of packets processed by bucket. */
+    uint64 byte_count = 2;    /* Number of bytes processed by bucket. */
+};
+
+/* Body of reply to OFPMP_GROUP request. */
+message ofp_group_stats {
+    uint32 group_id = 1;      /* Group identifier. */
+    uint32 ref_count = 2;     /* Number of flows or groups that directly
+                                 forward to this group. */
+    uint64 packet_count = 3;  /* Number of packets processed by group. */
+    uint64 byte_count = 4;    /* Number of bytes processed by group. */
+    uint32 duration_sec = 5;  /* Time group has been alive in seconds. */
+    uint32 duration_nsec = 6; /* Time group has been alive in nanoseconds
+                                 beyond duration_sec. */
+    repeated ofp_bucket_counter bucket_stats = 7; /* One counter set per
+                                                     bucket. */
+};
+
+/* Body of reply to OFPMP_GROUP_DESC request. */
+message ofp_group_desc {
+    ofp_group_type type = 1;       /* One of OFPGT_*. */
+    uint32 group_id = 2;           /* Group identifier. */
+    repeated ofp_bucket buckets = 3;   /* List of buckets - 0 or more. */
+};
+
+message ofp_group_entry {
+    ofp_group_type type = 1;       /* One of OFPGT_*. */
+    uint32 group_id = 2;           /* Group identifier. */
+    repeated ofp_bucket buckets = 3;   /* List of buckets - 0 or more. */
+    /* ofp_group_desc desc = 1; */
+    ofp_group_stats stats = 4;
+};
+
+/* Backward compatibility with 1.3.1 - avoid breaking the API. */
+//#define ofp_group_desc_stats ofp_group_desc
+
+/* Group configuration flags */
+enum ofp_group_capabilities {
+    OFPGFC_INVALID         = 0;
+    OFPGFC_SELECT_WEIGHT   = 1;  /* Support weight for select groups */
+    OFPGFC_SELECT_LIVENESS = 2;  /* Support liveness for select groups */
+    OFPGFC_CHAINING        = 4;  /* Support chaining groups */
+    OFPGFC_CHAINING_CHECKS = 8;  /* Check chaining for loops and delete */
+};
+
+/* Body of reply to OFPMP_GROUP_FEATURES request. Group features. */
+message ofp_group_features {
+    uint32  types = 1;         /* Bitmap of (1 << OFPGT_*) values supported. */
+    uint32  capabilities = 2;  /* Bitmap of OFPGFC_* capability supported. */
+    repeated uint32 max_groups = 3; /* Maximum number of groups for each type.
+                                     */
+    repeated uint32 actions = 4;    /* Bitmaps of (1 << OFPAT_*) values
+                                       supported. */
+};
+
+/* Body of OFPMP_METER and OFPMP_METER_CONFIG requests. */
+message ofp_meter_multipart_request {
+    uint32 meter_id = 1;      /* Meter instance, or OFPM_ALL. */
+};
+
+/* Statistics for each meter band */
+message ofp_meter_band_stats {
+    uint64        packet_band_count = 1;  /* Number of packets in band. */
+    uint64        byte_band_count = 2;    /* Number of bytes in band. */
+};
+
+/* Body of reply to OFPMP_METER request. Meter statistics. */
+message ofp_meter_stats {
+    uint32        meter_id = 1;        /* Meter instance. */
+    uint32        flow_count = 2;      /* Number of flows bound to meter. */
+    uint64        packet_in_count = 3; /* Number of packets in input. */
+    uint64        byte_in_count = 4;   /* Number of bytes in input. */
+    uint32        duration_sec = 5; /* Time meter has been alive in seconds. */
+    uint32        duration_nsec = 6;/* Time meter has been alive in nanoseconds
+                                       beyond duration_sec. */
+    repeated ofp_meter_band_stats band_stats = 7; /* The band_stats length is
+                                         inferred from the length field. */
+};
+
+/* Body of reply to OFPMP_METER_CONFIG request. Meter configuration. */
+message ofp_meter_config {
+    uint32        flags = 1;           /* All OFPMF_* that apply. */
+    uint32        meter_id = 2;        /* Meter instance. */
+    repeated ofp_meter_band_header bands = 3; /* The bands length is
+                                             inferred from the length field. */
+};
+
+/* Body of reply to OFPMP_METER_FEATURES request. Meter features. */
+message ofp_meter_features {
+    uint32    max_meter = 1;    /* Maximum number of meters. */
+    uint32    band_types = 2;   /* Bitmaps of (1 << OFPMBT_*) values supported.
+                                 */
+    uint32    capabilities = 3; /* Bitmaps of "ofp_meter_flags". */
+    uint32    max_bands = 4;    /* Maximum bands per meters */
+    uint32    max_color = 5;    /* Maximum color value */
+};
+
+/* Body for ofp_multipart_request/reply of type OFPMP_EXPERIMENTER. */
+message ofp_experimenter_multipart_header {
+    uint32 experimenter = 1;   /* Experimenter ID which takes the same form
+                                  as in struct ofp_experimenter_header. */
+    uint32 exp_type = 2;       /* Experimenter defined. */
+    bytes data = 3; /* Experimenter-defined arbitrary additional data. */
+};
+
+/* Experimenter extension. */
+message ofp_experimenter_header {
+    //ofp_header header;  /* Type OFPT_EXPERIMENTER. */
+    uint32 experimenter = 1;     /* Experimenter ID:
+                                 * - MSB 0: low-order bytes are IEEE OUI.
+                                 * - MSB != 0: defined by ONF. */
+    uint32 exp_type = 2;         /* Experimenter defined. */
+    bytes data = 3; /* Experimenter-defined arbitrary additional data. */
+};
+
+/* All ones is used to indicate all queues in a port (for stats retrieval). */
+//#define OFPQ_ALL      0xffffffff
+
+/* Min rate > 1000 means not configured. */
+//#define OFPQ_MIN_RATE_UNCFG      0xffff
+
+/* Max rate > 1000 means not configured. */
+//#define OFPQ_MAX_RATE_UNCFG      0xffff
+
+enum ofp_queue_properties {
+    OFPQT_INVALID       = 0;
+    OFPQT_MIN_RATE      = 1;      /* Minimum datarate guaranteed. */
+    OFPQT_MAX_RATE      = 2;      /* Maximum datarate. */
+    OFPQT_EXPERIMENTER  = 0xffff; /* Experimenter defined property. */
+};
+
+/* Common description for a queue. */
+message ofp_queue_prop_header {
+    uint32 property = 1;   /* One of OFPQT_. */
+    uint32 len = 2;        /* Length of property, including this header. */
+};
+
+/* Min-Rate queue property description. */
+message ofp_queue_prop_min_rate {
+    ofp_queue_prop_header prop_header = 1;/* prop: OFPQT_MIN, len: 16. */
+    uint32 rate = 2;       /* In 1/10 of a percent = 0;>1000 -> disabled. */
+};
+
+/* Max-Rate queue property description. */
+message ofp_queue_prop_max_rate {
+    ofp_queue_prop_header prop_header = 1;/* prop: OFPQT_MAX, len: 16. */
+    uint32 rate = 2;       /* In 1/10 of a percent = 0;>1000 -> disabled. */
+};
+
+/* Experimenter queue property description. */
+message ofp_queue_prop_experimenter {
+    ofp_queue_prop_header prop_header = 1;/* prop: OFPQT_EXPERIMENTER */
+    uint32 experimenter = 2;         /* Experimenter ID which takes the same
+                                          form as in struct
+                                          ofp_experimenter_header. */
+    bytes data = 3;                    /* Experimenter defined data. */
+};
+
+/* Full description for a queue. */
+message ofp_packet_queue {
+    uint32 queue_id = 1;    /* id for the specific queue. */
+    uint32 port = 2;        /* Port this queue is attached to. */
+    repeated ofp_queue_prop_header properties = 4; /* List of properties. */
+};
+
+/* Query for port queue configuration. */
+message ofp_queue_get_config_request {
+    //ofp_header header;
+    uint32 port = 1;        /* Port to be queried. Should refer
+                              to a valid physical port (i.e. <= OFPP_MAX),
+                              or OFPP_ANY to request all configured
+                              queues.*/
+};
+
+/* Queue configuration for a given port. */
+message ofp_queue_get_config_reply {
+    //ofp_header header;
+    uint32 port = 1;
+    repeated ofp_packet_queue queues = 2; /* List of configured queues. */
+};
+
+/* OFPAT_SET_QUEUE action struct: send packets to given queue on port. */
+message ofp_action_set_queue {
+    uint32 type = 1;           /* OFPAT_SET_QUEUE. */
+    uint32 queue_id = 3;       /* Queue id for the packets. */
+};
+
+message ofp_queue_stats_request {
+    uint32 port_no = 1;       /* All ports if OFPP_ANY. */
+    uint32 queue_id = 2;      /* All queues if OFPQ_ALL. */
+};
+
+message ofp_queue_stats {
+    uint32 port_no = 1;
+    uint32 queue_id = 2;      /* Queue i.d */
+    uint64 tx_bytes = 3;      /* Number of transmitted bytes. */
+    uint64 tx_packets = 4;    /* Number of transmitted packets. */
+    uint64 tx_errors = 5;     /* Number of packets dropped due to overrun. */
+    uint32 duration_sec = 6;  /* Time queue has been alive in seconds. */
+    uint32 duration_nsec = 7; /* Time queue has been alive in nanoseconds
+                                 beyond duration_sec. */
+};
+
+/* Configures the "role" of the sending controller.  The default role is:
+ *
+ *    - Equal (OFPCR_ROLE_EQUAL), which allows the controller access to all
+ *      OpenFlow features. All controllers have equal responsibility.
+ *
+ * The other possible roles are a related pair:
+ *
+ *    - Master (OFPCR_ROLE_MASTER) is equivalent to Equal, except that there
+ *      may be at most one Master controller at a time: when a controller
+ *      configures itself as Master, any existing Master is demoted to the
+ *      Slave role.
+ *
+ *    - Slave (OFPCR_ROLE_SLAVE) allows the controller read-only access to
+ *      OpenFlow features.  In particular attempts to modify the flow table
+ *      will be rejected with an OFPBRC_EPERM error.
+ *
+ *      Slave controllers do not receive OFPT_PACKET_IN or OFPT_FLOW_REMOVED
+ *      messages, but they do receive OFPT_PORT_STATUS messages.
+ */
+
+/* Controller roles. */
+enum ofp_controller_role {
+    OFPCR_ROLE_NOCHANGE = 0;    /* Don't change current role. */
+    OFPCR_ROLE_EQUAL    = 1;    /* Default role, full access. */
+    OFPCR_ROLE_MASTER   = 2;    /* Full access, at most one master. */
+    OFPCR_ROLE_SLAVE    = 3;    /* Read-only access. */
+};
+
+/* Role request and reply message. */
+message ofp_role_request {
+    //ofp_header header;        /* Type OFPT_ROLE_REQUEST/OFPT_ROLE_REPLY. */
+    ofp_controller_role role = 1; /* One of OFPCR_ROLE_*. */
+    uint64 generation_id = 2;     /* Master Election Generation Id */
+};
+
+/* Asynchronous message configuration. */
+message ofp_async_config {
+    //ofp_header header;    /* OFPT_GET_ASYNC_REPLY or OFPT_SET_ASYNC. */
+    repeated uint32 packet_in_mask = 1;   /* Bitmasks of OFPR_* values. */
+    repeated uint32 port_status_mask = 2; /* Bitmasks of OFPPR_* values. */
+    repeated uint32 flow_removed_mask = 3;/* Bitmasks of OFPRR_* values. */
+};
+
+
+/* ADDITIONAL VOLTHA SPECIFIC MESSAGE TYPES, AIDING RPC CALLS */
+
+message FlowTableUpdate {
+    string id = 1;  // Device.id or LogicalDevice.id
+    ofp_flow_mod flow_mod = 2;
+}
+
+message FlowGroupTableUpdate {
+    string id = 1;  // Device.id or LogicalDevice.id
+    ofp_group_mod group_mod = 2;
+}
+
+message Flows {
+    repeated ofp_flow_stats items = 1;
+}
+
+message FlowGroups {
+    repeated ofp_group_entry items = 1;
+}
+
+message PacketIn {
+    string id = 1;  // LogicalDevice.id
+    ofp_packet_in packet_in = 2;
+}
+
+message PacketOut {
+    string id = 1;  // LogicalDevice.id
+    ofp_packet_out packet_out = 2;
+}
diff --git a/experiments/netconf/proto2yang/openflow_13_orig.proto b/experiments/netconf/proto2yang/openflow_13_orig.proto
new file mode 100644
index 0000000..01b5059
--- /dev/null
+++ b/experiments/netconf/proto2yang/openflow_13_orig.proto
@@ -0,0 +1,2275 @@
+/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
+ * Junior University
+ * Copyright (c) 2011, 2012 Open Networking Foundation
+ *
+ * We are making the OpenFlow specification and associated documentation
+ * (Software) available for public use and benefit with the expectation
+ * that others will use, modify and enhance the Software and contribute
+ * those enhancements back to the community. However, since we would
+ * like to make the Software available for broadest use, with as few
+ * restrictions as possible permission is hereby granted, free of
+ * charge, to any person obtaining a copy of this Software to deal in
+ * the Software under the copyrights without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The name and trademarks of copyright holder(s) may NOT be used in
+ * advertising or publicity pertaining to the Software or any
+ * derivatives without specific, written prior permission.
+ */
+
+/* OpenFlow: protocol between controller and datapath. */
+
+/*
+ * This is a relatively straightforward rendering of OpenFlow message
+ * definitions into protocol buffer messages. We preserved the snake
+ * case syntax, and made the following changes:
+ * - all pad fields dropped
+ * - for each enum value above 0x7fffffff the MSB is dropped. For example,
+ *   0xffffffff is now 0x7fffffff.
+ * - '<type> thing[...]' is replaced with 'repeated <type> thing'
+ * - 'char thing[...]' is replaced with 'string thing'
+ * - 'uint8_t data[...]' is replaced with 'bytes data'
+ * - the following systematic changes are done to various integer types:
+ *   uint8_t  -> uint32
+ *   uint16_t -> uint32
+ *   uint32_t -> uint32
+ *   uint64_t -> uint64
+ * - removed most length, len, size fields where these values can be determined
+ *   from the explicitly encoded length of "repeated" protobuf fields.
+ * - explicit use of enum types whereever it is unambigous (and not used as
+ *   bitmask/flags value.
+ *
+ */
+syntax = "proto3";
+
+package openflow_13;
+
+
+/* Version number:
+ * OpenFlow versions released: 0x01 = 1.0 ; 0x02 = 1.1 ; 0x03 = 1.2
+ *     0x04 = 1.3
+ */
+/* The most significant bit in the version field is reserved and must
+ * be set to zero.
+ */
+//#define OFP_VERSION   0x04
+//#define PIPELINE_TABLES 64
+//#define OFP_MAX_TABLE_NAME_LEN 32
+//#define OFP_MAX_PORT_NAME_LEN  16
+/* Official IANA registered port for OpenFlow. */
+//#define OFP_TCP_PORT  6653
+//#define OFP_SSL_PORT  6653
+
+//#define OFP_ETH_ALEN 6          /* Bytes in an Ethernet address. */
+
+/* Port numbering. Ports are numbered starting from 1. */
+enum ofp_port_no {
+    OFPP_INVALID    = 0;
+
+    /* Maximum number of physical and logical switch ports. */
+    OFPP_MAX        = 0x7fffff00;
+
+    /* Reserved OpenFlow Port (fake output "ports"). */
+    OFPP_IN_PORT    = 0x7ffffff8;  /* Send the packet out the input port.  This
+                                      reserved port must be explicitly used
+                                      in order to send back out of the input
+                                      port. */
+    OFPP_TABLE      = 0x7ffffff9;  /* Submit the packet to the first flow table
+                                      NB: This destination port can only be
+                                      used in packet-out messages. */
+    OFPP_NORMAL     = 0x7ffffffa;  /* Forward using non-OpenFlow pipeline. */
+    OFPP_FLOOD      = 0x7ffffffb;  /* Flood using non-OpenFlow pipeline. */
+    OFPP_ALL        = 0x7ffffffc;  /* All standard ports except input port. */
+    OFPP_CONTROLLER = 0x7ffffffd;  /* Send to controller. */
+    OFPP_LOCAL      = 0x7ffffffe;  /* Local openflow "port". */
+    OFPP_ANY        = 0x7fffffff;  /* Special value used in some requests when
+                                      no port is specified (i.e. wildcarded).*/
+};
+
+enum ofp_type {
+
+    /* Immutable messages. */
+    OFPT_HELLO                      = 0;  /* Symmetric message */
+    OFPT_ERROR                      = 1;  /* Symmetric message */
+    OFPT_ECHO_REQUEST               = 2;  /* Symmetric message */
+    OFPT_ECHO_REPLY                 = 3;  /* Symmetric message */
+    OFPT_EXPERIMENTER               = 4;  /* Symmetric message */
+
+    /* Switch configuration messages. */
+    OFPT_FEATURES_REQUEST           = 5;  /* Controller/switch message */
+    OFPT_FEATURES_REPLY             = 6;  /* Controller/switch message */
+    OFPT_GET_CONFIG_REQUEST         = 7;  /* Controller/switch message */
+    OFPT_GET_CONFIG_REPLY           = 8;  /* Controller/switch message */
+    OFPT_SET_CONFIG                 = 9;  /* Controller/switch message */
+
+    /* Asynchronous messages. */
+    OFPT_PACKET_IN                  = 10; /* Async message */
+    OFPT_FLOW_REMOVED               = 11; /* Async message */
+    OFPT_PORT_STATUS                = 12; /* Async message */
+
+    /* Controller command messages. */
+    OFPT_PACKET_OUT                 = 13; /* Controller/switch message */
+    OFPT_FLOW_MOD                   = 14; /* Controller/switch message */
+    OFPT_GROUP_MOD                  = 15; /* Controller/switch message */
+    OFPT_PORT_MOD                   = 16; /* Controller/switch message */
+    OFPT_TABLE_MOD                  = 17; /* Controller/switch message */
+
+    /* Multipart messages. */
+    OFPT_MULTIPART_REQUEST          = 18; /* Controller/switch message */
+    OFPT_MULTIPART_REPLY            = 19; /* Controller/switch message */
+
+    /* Barrier messages. */
+    OFPT_BARRIER_REQUEST            = 20; /* Controller/switch message */
+    OFPT_BARRIER_REPLY              = 21; /* Controller/switch message */
+
+    /* Queue Configuration messages. */
+    OFPT_QUEUE_GET_CONFIG_REQUEST   = 22;  /* Controller/switch message */
+    OFPT_QUEUE_GET_CONFIG_REPLY     = 23;  /* Controller/switch message */
+
+    /* Controller role change request messages. */
+    OFPT_ROLE_REQUEST               = 24; /* Controller/switch message */
+    OFPT_ROLE_REPLY                 = 25; /* Controller/switch message */
+
+    /* Asynchronous message configuration. */
+    OFPT_GET_ASYNC_REQUEST          = 26; /* Controller/switch message */
+    OFPT_GET_ASYNC_REPLY            = 27; /* Controller/switch message */
+    OFPT_SET_ASYNC                  = 28; /* Controller/switch message */
+
+    /* Meters and rate limiters configuration messages. */
+    OFPT_METER_MOD                  = 29; /* Controller/switch message */
+};
+
+/* Header on all OpenFlow packets. */
+message ofp_header {
+    uint32 version = 1;    /* OFP_VERSION. */
+    ofp_type type = 2;     /* One of the OFPT_ constants. */
+    uint32 xid = 3;        /* Transaction id associated with this packet.
+                              Replies use the same id as was in the request
+                              to facilitate pairing. */
+};
+
+/* Hello elements types.
+ */
+enum ofp_hello_elem_type {
+    OFPHET_INVALID                = 0;
+    OFPHET_VERSIONBITMAP          = 1;  /* Bitmap of version supported. */
+};
+
+/* Common header for all Hello Elements */
+message ofp_hello_elem_header {
+    ofp_hello_elem_type type = 1;       /* One of OFPHET_*. */
+    oneof element {
+        ofp_hello_elem_versionbitmap versionbitmap = 2;
+    }
+};
+
+/* Version bitmap Hello Element */
+message ofp_hello_elem_versionbitmap {
+    repeated uint32 bitmaps = 2;   /* List of bitmaps - supported versions */
+};
+
+/* OFPT_HELLO.  This message includes zero or more hello elements having
+ * variable size. Unknown elements types must be ignored/skipped, to allow
+ * for future extensions. */
+message ofp_hello {
+    //ofp_header header;
+    /* Hello element list */
+    repeated ofp_hello_elem_header elements = 1; /* 0 or more */
+};
+
+//#define OFP_DEFAULT_MISS_SEND_LEN   128
+
+enum ofp_config_flags {
+    /* Handling of IP fragments. */
+    OFPC_FRAG_NORMAL   = 0;       /* No special handling for fragments. */
+    OFPC_FRAG_DROP     = 1;       /* Drop fragments. */
+    OFPC_FRAG_REASM    = 2;       /* Reassemble (only if OFPC_IP_REASM set). */
+    OFPC_FRAG_MASK     = 3;       /* Bitmask of flags dealing with frag. */
+};
+
+/* Switch configuration. */
+message ofp_switch_config {
+    //ofp_header header;
+    uint32 flags = 1;             /* Bitmap of OFPC_* flags. */
+    uint32 miss_send_len = 2;     /* Max bytes of packet that datapath
+                                     should send to the controller. See
+                                     ofp_controller_max_len for valid values.
+                                   */
+};
+
+/* Flags to configure the table. Reserved for future use. */
+enum ofp_table_config {
+    OFPTC_INVALID = 0;
+    OFPTC_DEPRECATED_MASK = 3;     /* Deprecated bits */
+};
+
+/* Table numbering. Tables can use any number up to OFPT_MAX. */
+enum ofp_table {
+
+    OFPTT_INVALID = 0;
+
+    /* Last usable table number. */
+    OFPTT_MAX        = 0xfe;
+
+    /* Fake tables. */
+    OFPTT_ALL        = 0xff;   /* Wildcard table used for table config,
+                                  flow stats and flow deletes. */
+};
+
+
+/* Configure/Modify behavior of a flow table */
+message ofp_table_mod {
+    //ofp_header header;
+    uint32 table_id = 1;  /* ID of the table, OFPTT_ALL indicates all tables */
+    uint32 config = 2;    /* Bitmap of OFPTC_* flags */
+};
+
+/* Capabilities supported by the datapath. */
+enum ofp_capabilities {
+    OFPC_INVALID        = 0;
+    OFPC_FLOW_STATS     = 1;    /* Flow statistics. */
+    OFPC_TABLE_STATS    = 2;    /* Table statistics. */
+    OFPC_PORT_STATS     = 4;    /* Port statistics. */
+    OFPC_GROUP_STATS    = 8;    /* Group statistics. */
+    OFPC_IP_REASM       = 32;   /* Can reassemble IP fragments. */
+    OFPC_QUEUE_STATS    = 64;   /* Queue statistics. */
+    OFPC_PORT_BLOCKED   = 256;  /* Switch will block looping ports. */
+};
+
+/* Flags to indicate behavior of the physical port.  These flags are
+ * used in ofp_port to describe the current configuration.  They are
+ * used in the ofp_port_mod message to configure the port's behavior.
+ */
+enum ofp_port_config {
+    OFPPC_INVALID      = 0;
+    OFPPC_PORT_DOWN    = 1;   /* Port is administratively down. */
+
+    OFPPC_NO_RECV      = 4;   /* Drop all packets received by port. */
+    OFPPC_NO_FWD       = 32;  /* Drop packets forwarded to port. */
+    OFPPC_NO_PACKET_IN = 64;  /* Do not send packet-in msgs for port. */
+};
+
+/* Current state of the physical port.  These are not configurable from
+ * the controller.
+ */
+enum ofp_port_state {
+    OFPPS_INVALID      = 0;
+    OFPPS_LINK_DOWN    = 1;  /* No physical link present. */
+    OFPPS_BLOCKED      = 2;  /* Port is blocked */
+    OFPPS_LIVE         = 4;  /* Live for Fast Failover Group. */
+};
+
+/* Features of ports available in a datapath. */
+enum ofp_port_features {
+    OFPPF_INVALID    = 0;
+    OFPPF_10MB_HD    = 1;      /* 10 Mb half-duplex rate support. */
+    OFPPF_10MB_FD    = 2;      /* 10 Mb full-duplex rate support. */
+    OFPPF_100MB_HD   = 4;      /* 100 Mb half-duplex rate support. */
+    OFPPF_100MB_FD   = 8;      /* 100 Mb full-duplex rate support. */
+    OFPPF_1GB_HD     = 16;     /* 1 Gb half-duplex rate support. */
+    OFPPF_1GB_FD     = 32;     /* 1 Gb full-duplex rate support. */
+    OFPPF_10GB_FD    = 64;     /* 10 Gb full-duplex rate support. */
+    OFPPF_40GB_FD    = 128;    /* 40 Gb full-duplex rate support. */
+    OFPPF_100GB_FD   = 256;    /* 100 Gb full-duplex rate support. */
+    OFPPF_1TB_FD     = 512;    /* 1 Tb full-duplex rate support. */
+    OFPPF_OTHER      = 1024;   /* Other rate, not in the list. */
+    OFPPF_COPPER     = 2048;   /* Copper medium. */
+    OFPPF_FIBER      = 4096;   /* Fiber medium. */
+    OFPPF_AUTONEG    = 8192;   /* Auto-negotiation. */
+    OFPPF_PAUSE      = 16384;  /* Pause. */
+    OFPPF_PAUSE_ASYM = 32768;  /* Asymmetric pause. */
+};
+
+/* Description of a port */
+message ofp_port {
+    uint32 port_no = 1;
+    repeated uint32 hw_addr = 2; // [OFP_ETH_ALEN];
+    string name = 3;             /* Null-terminated */
+
+    uint32 config = 4;           /* Bitmap of OFPPC_* flags. */
+    uint32 state = 5;            /* Bitmap of OFPPS_* flags. */
+
+    /* Bitmaps of OFPPF_* that describe features.  All bits zeroed if
+     * unsupported or unavailable. */
+    uint32 curr = 6;           /* Current features. */
+    uint32 advertised = 7;     /* Features being advertised by the port. */
+    uint32 supported = 8;      /* Features supported by the port. */
+    uint32 peer = 9;           /* Features advertised by peer. */
+    uint32 curr_speed = 10;    /* Current port bitrate in kbps. */
+    uint32 max_speed = 11;     /* Max port bitrate in kbps */
+};
+
+/* Switch features. */
+message ofp_switch_features {
+    //ofp_header header;
+    uint64 datapath_id = 1;   /* Datapath unique ID.  The lower 48-bits are for
+                                 a MAC address, while the upper 16-bits are
+                                 implementer-defined. */
+
+    uint32 n_buffers = 2;     /* Max packets buffered at once. */
+
+    uint32 n_tables = 3;      /* Number of tables supported by datapath. */
+    uint32 auxiliary_id = 4;  /* Identify auxiliary connections */
+
+    /* Features. */
+    uint32 capabilities = 5;  /* Bitmap of support "ofp_capabilities". */
+};
+
+/* What changed about the physical port */
+enum ofp_port_reason {
+    OFPPR_ADD     = 0;         /* The port was added. */
+    OFPPR_DELETE  = 1;         /* The port was removed. */
+    OFPPR_MODIFY  = 2;         /* Some attribute of the port has changed. */
+};
+
+/* A physical port has changed in the datapath */
+message ofp_port_status {
+    //ofp_header header;
+    ofp_port_reason reason = 1; /* One of OFPPR_*. */
+    ofp_port desc = 2;
+};
+
+/* Modify behavior of the physical port */
+message ofp_port_mod {
+    //ofp_header header;
+    uint32 port_no = 1;
+    repeated uint32 hw_addr = 2; //[OFP_ETH_ALEN];
+                                      /* The hardware address is not
+                                         configurable.  This is used to
+                                         sanity-check the request, so it must
+                                         be the same as returned in an
+                                         ofp_port struct. */
+    uint32 config = 3;        /* Bitmap of OFPPC_* flags. */
+    uint32 mask = 4;          /* Bitmap of OFPPC_* flags to be changed. */
+
+    uint32 advertise = 5;     /* Bitmap of OFPPF_*.  Zero all bits to prevent
+                                 any action taking place. */
+};
+
+/* ## -------------------------- ## */
+/* ## OpenFlow Extensible Match. ## */
+/* ## -------------------------- ## */
+
+/* The match type indicates the match structure (set of fields that compose the
+ * match) in use. The match type is placed in the type field at the beginning
+ * of all match structures. The "OpenFlow Extensible Match" type corresponds
+ * to OXM TLV format described below and must be supported by all OpenFlow
+ * switches. Extensions that define other match types may be published on the
+ * ONF wiki. Support for extensions is optional.
+ */
+enum ofp_match_type {
+    OFPMT_STANDARD = 0;       /* Deprecated. */
+    OFPMT_OXM      = 1;       /* OpenFlow Extensible Match */
+};
+
+/* Fields to match against flows */
+message ofp_match {
+    ofp_match_type type = 1;         /* One of OFPMT_* */
+    repeated ofp_oxm_field oxm_fields = 2;  /* 0 or more */
+};
+
+/* Components of a OXM TLV header.
+ * Those macros are not valid for the experimenter class, macros for the
+ * experimenter class will depend on the experimenter header used. */
+//#define OXM_HEADER__(CLASS, FIELD, HASMASK, LENGTH) \
+//    (((CLASS) << 16) | ((FIELD) << 9) | ((HASMASK) << 8) | (LENGTH))
+//#define OXM_HEADER(CLASS, FIELD, LENGTH) \
+//    OXM_HEADER__(CLASS, FIELD, 0, LENGTH)
+//#define OXM_HEADER_W(CLASS, FIELD, LENGTH) \
+//    OXM_HEADER__(CLASS, FIELD, 1, (LENGTH) * 2)
+//#define OXM_CLASS(HEADER) ((HEADER) >> 16)
+//#define OXM_FIELD(HEADER) (((HEADER) >> 9) & 0x7f)
+//#define OXM_TYPE(HEADER) (((HEADER) >> 9) & 0x7fffff)
+//#define OXM_HASMASK(HEADER) (((HEADER) >> 8) & 1)
+//#define OXM_LENGTH(HEADER) ((HEADER) & 0xff)
+//
+//#define OXM_MAKE_WILD_HEADER(HEADER) \
+//    OXM_HEADER_W(OXM_CLASS(HEADER), OXM_FIELD(HEADER), OXM_LENGTH(HEADER))
+
+/* OXM Class IDs.
+ * The high order bit differentiate reserved classes from member classes.
+ * Classes 0x0000 to 0x7FFF are member classes, allocated by ONF.
+ * Classes 0x8000 to 0xFFFE are reserved classes, reserved for standardisation.
+ */
+enum ofp_oxm_class {
+    OFPXMC_NXM_0          = 0x0000;    /* Backward compatibility with NXM */
+    OFPXMC_NXM_1          = 0x0001;    /* Backward compatibility with NXM */
+    OFPXMC_OPENFLOW_BASIC = 0x8000;    /* Basic class for OpenFlow */
+    OFPXMC_EXPERIMENTER   = 0xFFFF;    /* Experimenter class */
+};
+
+/* OXM Flow field types for OpenFlow basic class. */
+enum oxm_ofb_field_types {
+    OFPXMT_OFB_IN_PORT        = 0;  /* Switch input port. */
+    OFPXMT_OFB_IN_PHY_PORT    = 1;  /* Switch physical input port. */
+    OFPXMT_OFB_METADATA       = 2;  /* Metadata passed between tables. */
+    OFPXMT_OFB_ETH_DST        = 3;  /* Ethernet destination address. */
+    OFPXMT_OFB_ETH_SRC        = 4;  /* Ethernet source address. */
+    OFPXMT_OFB_ETH_TYPE       = 5;  /* Ethernet frame type. */
+    OFPXMT_OFB_VLAN_VID       = 6;  /* VLAN id. */
+    OFPXMT_OFB_VLAN_PCP       = 7;  /* VLAN priority. */
+    OFPXMT_OFB_IP_DSCP        = 8;  /* IP DSCP (6 bits in ToS field). */
+    OFPXMT_OFB_IP_ECN         = 9;  /* IP ECN (2 bits in ToS field). */
+    OFPXMT_OFB_IP_PROTO       = 10; /* IP protocol. */
+    OFPXMT_OFB_IPV4_SRC       = 11; /* IPv4 source address. */
+    OFPXMT_OFB_IPV4_DST       = 12; /* IPv4 destination address. */
+    OFPXMT_OFB_TCP_SRC        = 13; /* TCP source port. */
+    OFPXMT_OFB_TCP_DST        = 14; /* TCP destination port. */
+    OFPXMT_OFB_UDP_SRC        = 15; /* UDP source port. */
+    OFPXMT_OFB_UDP_DST        = 16; /* UDP destination port. */
+    OFPXMT_OFB_SCTP_SRC       = 17; /* SCTP source port. */
+    OFPXMT_OFB_SCTP_DST       = 18; /* SCTP destination port. */
+    OFPXMT_OFB_ICMPV4_TYPE    = 19; /* ICMP type. */
+    OFPXMT_OFB_ICMPV4_CODE    = 20; /* ICMP code. */
+    OFPXMT_OFB_ARP_OP         = 21; /* ARP opcode. */
+    OFPXMT_OFB_ARP_SPA        = 22; /* ARP source IPv4 address. */
+    OFPXMT_OFB_ARP_TPA        = 23; /* ARP target IPv4 address. */
+    OFPXMT_OFB_ARP_SHA        = 24; /* ARP source hardware address. */
+    OFPXMT_OFB_ARP_THA        = 25; /* ARP target hardware address. */
+    OFPXMT_OFB_IPV6_SRC       = 26; /* IPv6 source address. */
+    OFPXMT_OFB_IPV6_DST       = 27; /* IPv6 destination address. */
+    OFPXMT_OFB_IPV6_FLABEL    = 28; /* IPv6 Flow Label */
+    OFPXMT_OFB_ICMPV6_TYPE    = 29; /* ICMPv6 type. */
+    OFPXMT_OFB_ICMPV6_CODE    = 30; /* ICMPv6 code. */
+    OFPXMT_OFB_IPV6_ND_TARGET = 31; /* Target address for ND. */
+    OFPXMT_OFB_IPV6_ND_SLL    = 32; /* Source link-layer for ND. */
+    OFPXMT_OFB_IPV6_ND_TLL    = 33; /* Target link-layer for ND. */
+    OFPXMT_OFB_MPLS_LABEL     = 34; /* MPLS label. */
+    OFPXMT_OFB_MPLS_TC        = 35; /* MPLS TC. */
+    OFPXMT_OFB_MPLS_BOS       = 36; /* MPLS BoS bit. */
+    OFPXMT_OFB_PBB_ISID       = 37; /* PBB I-SID. */
+    OFPXMT_OFB_TUNNEL_ID      = 38; /* Logical Port Metadata. */
+    OFPXMT_OFB_IPV6_EXTHDR    = 39; /* IPv6 Extension Header pseudo-field */
+};
+
+/* OXM Flow match fields */
+message ofp_oxm_field {
+    ofp_oxm_class oxm_class = 1;
+    oneof field {
+        /* 2 and 3 reserved for NXM_0 and NXM-1 OXM classes */
+        ofp_oxm_ofb_field ofb_field = 4;
+        ofp_oxm_experimenter_field experimenter_field = 5;
+    }
+}
+
+/* OXM OpenFlow Basic Match Field */
+message ofp_oxm_ofb_field {
+    oxm_ofb_field_types type = 1;
+    bool has_mask = 2;
+    oneof value {
+
+        /* OpenFlow port on which the packet was received.
+         * May be a physical port, a logical port, or the reserved port OFPP_LOCAL
+         *
+         * Prereqs: None.
+         *
+         * Format: 32-bit integer in network byte order.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_IN_PORT    OXM_HEADER  (0x8000, OFPXMT_OFB_IN_PORT, 4)
+        uint32 port = 3; /* Used for OFPXMT_OFB_IN_PORT */
+
+        /* Physical port on which the packet was received.
+         *
+         * Consider a packet received on a tunnel interface defined over a link
+         * aggregation group (LAG) with two physical port members.  If the tunnel
+         * interface is the logical port bound to OpenFlow.  In this case,
+         * OFPXMT_OF_IN_PORT is the tunnel's port number and OFPXMT_OF_IN_PHY_PORT is
+         * the physical port number of the LAG on which the tunnel is configured.
+         *
+         * When a packet is received directly on a physical port and not processed by a
+         * logical port, OFPXMT_OF_IN_PORT and OFPXMT_OF_IN_PHY_PORT have the same
+         * value.
+         *
+         * This field is usually not available in a regular match and only available
+         * in ofp_packet_in messages when it's different from OXM_OF_IN_PORT.
+         *
+         * Prereqs: OXM_OF_IN_PORT must be present.
+         *
+         * Format: 32-bit integer in network byte order.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_IN_PHY_PORT OXM_HEADER  (0x8000, OFPXMT_OFB_IN_PHY_PORT, 4)
+        uint32 physical_port = 4; /* Used for OFPXMT_OF_IN_PHY_PORT */
+
+        /* Table metadata.
+         *
+         * Prereqs: None.
+         *
+         * Format: 64-bit integer in network byte order.
+         *
+         * Masking: Arbitrary masks.
+         */
+        //#define OXM_OF_METADATA   OXM_HEADER  (0x8000, OFPXMT_OFB_METADATA, 8)
+        //#define OXM_OF_METADATA_W OXM_HEADER_W(0x8000, OFPXMT_OFB_METADATA, 8)
+        uint64 table_metadata = 5; /* Used for OFPXMT_OFB_METADATA */
+
+        /* Source or destination address in Ethernet header.
+         *
+         * Prereqs: None.
+         *
+         * Format: 48-bit Ethernet MAC address.
+         *
+         * Masking: Arbitrary masks. */
+        //#define OXM_OF_ETH_DST    OXM_HEADER  (0x8000, OFPXMT_OFB_ETH_DST, 6)
+        //#define OXM_OF_ETH_DST_W  OXM_HEADER_W(0x8000, OFPXMT_OFB_ETH_DST, 6)
+        //#define OXM_OF_ETH_SRC    OXM_HEADER  (0x8000, OFPXMT_OFB_ETH_SRC, 6)
+        //#define OXM_OF_ETH_SRC_W  OXM_HEADER_W(0x8000, OFPXMT_OFB_ETH_SRC, 6)
+        bytes eth_dst = 6; /* Used for OFPXMT_OFB_ETH_DST (exactly 6 bytes) */
+        bytes eth_src = 7; /* Used for OFPXMT_OFB_ETH_SRC (exactly 6 bytes) */
+
+        /* Packet's Ethernet type.
+         *
+         * Prereqs: None.
+         *
+         * Format: 16-bit integer in network byte order.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_ETH_TYPE   OXM_HEADER  (0x8000, OFPXMT_OFB_ETH_TYPE,2)
+        uint32 eth_type = 8; /* Used for OFPXMT_OFB_ETH_TYPE */
+
+        /* 802.1Q VID.
+         *
+         * For a packet with an 802.1Q header, this is the VLAN-ID (VID) from the
+         * outermost tag, with the CFI bit forced to 1. For a packet with no 802.1Q
+         * header, this has value OFPVID_NONE.
+         *
+         * Prereqs: None.
+         *
+         * Format: 16-bit integer in network byte order with bit 13 indicating
+         * presence of VLAN header and 3 most-significant bits forced to 0.
+         * Only the lower 13 bits have meaning.
+         *
+         * Masking: Arbitrary masks.
+         *
+         * This field can be used in various ways:
+         *
+         *   - If it is not constrained at all, the nx_match matches packets without
+         *     an 802.1Q header or with an 802.1Q header that has any VID value.
+         *
+         *   - Testing for an exact match with 0x0 matches only packets without
+         *     an 802.1Q header.
+         *
+         *   - Testing for an exact match with a VID value with CFI=1 matches packets
+         *     that have an 802.1Q header with a specified VID.
+         *
+         *   - Testing for an exact match with a nonzero VID value with CFI=0 does
+         *     not make sense.  The switch may reject this combination.
+         *
+         *   - Testing with nxm_value=0, nxm_mask=0x0fff matches packets with no 802.1Q
+         *     header or with an 802.1Q header with a VID of 0.
+         *
+         *   - Testing with nxm_value=0x1000, nxm_mask=0x1000 matches packets with
+         *     an 802.1Q header that has any VID value.
+         */
+        //#define OXM_OF_VLAN_VID   OXM_HEADER  (0x8000, OFPXMT_OFB_VLAN_VID, 2)
+        //#define OXM_OF_VLAN_VID_W OXM_HEADER_W(0x8000, OFPXMT_OFB_VLAN_VID, 2)
+        uint32 vlan_vid = 9; /* Used for OFPXMT_OFB_VLAN_VID */
+
+        /* 802.1Q PCP.
+         *
+         * For a packet with an 802.1Q header, this is the VLAN-PCP from the
+         * outermost tag.  For a packet with no 802.1Q header, this has value
+         * 0.
+         *
+         * Prereqs: OXM_OF_VLAN_VID must be different from OFPVID_NONE.
+         *
+         * Format: 8-bit integer with 5 most-significant bits forced to 0.
+         * Only the lower 3 bits have meaning.
+         *
+         * Masking: Not maskable.
+         */
+        //#define OXM_OF_VLAN_PCP   OXM_HEADER  (0x8000, OFPXMT_OFB_VLAN_PCP, 1)
+        uint32 vlan_pcp = 10; /* Used for OFPXMT_OFB_VLAN_PCP */
+
+        /* The Diff Serv Code Point (DSCP) bits of the IP header.
+         * Part of the IPv4 ToS field or the IPv6 Traffic Class field.
+         *
+         * Prereqs: OXM_OF_ETH_TYPE must be either 0x0800 or 0x86dd.
+         *
+         * Format: 8-bit integer with 2 most-significant bits forced to 0.
+         * Only the lower 6 bits have meaning.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_IP_DSCP     OXM_HEADER  (0x8000, OFPXMT_OFB_IP_DSCP, 1)
+        uint32 ip_dscp = 11; /* Used for OFPXMT_OFB_IP_DSCP */
+
+        /* The ECN bits of the IP header.
+         * Part of the IPv4 ToS field or the IPv6 Traffic Class field.
+         *
+         * Prereqs: OXM_OF_ETH_TYPE must be either 0x0800 or 0x86dd.
+         *
+         * Format: 8-bit integer with 6 most-significant bits forced to 0.
+         * Only the lower 2 bits have meaning.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_IP_ECN     OXM_HEADER  (0x8000, OFPXMT_OFB_IP_ECN, 1)
+        uint32 ip_ecn = 12; /* Used for OFPXMT_OFB_IP_ECN */
+
+        /* The "protocol" byte in the IP header.
+         *
+         * Prereqs: OXM_OF_ETH_TYPE must be either 0x0800 or 0x86dd.
+         *
+         * Format: 8-bit integer.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_IP_PROTO   OXM_HEADER  (0x8000, OFPXMT_OFB_IP_PROTO, 1)
+        uint32 ip_proto = 13; /* Used for OFPXMT_OFB_IP_PROTO */
+
+        /* The source or destination address in the IP header.
+         *
+         * Prereqs: OXM_OF_ETH_TYPE must match 0x0800 exactly.
+         *
+         * Format: 32-bit integer in network byte order.
+         *
+         * Masking: Arbitrary masks.
+         */
+        //#define OXM_OF_IPV4_SRC     OXM_HEADER  (0x8000, OFPXMT_OFB_IPV4_SRC, 4)
+        //#define OXM_OF_IPV4_SRC_W   OXM_HEADER_W(0x8000, OFPXMT_OFB_IPV4_SRC, 4)
+        //#define OXM_OF_IPV4_DST     OXM_HEADER  (0x8000, OFPXMT_OFB_IPV4_DST, 4)
+        //#define OXM_OF_IPV4_DST_W   OXM_HEADER_W(0x8000, OFPXMT_OFB_IPV4_DST, 4)
+        uint32 ipv4_src = 14; /* Used for OFPXMT_OFB_IPV4_SRC */
+        uint32 ipv4_dst = 15; /* Used for OFPXMT_OFB_IPV4_DST */
+
+        /* The source or destination port in the TCP header.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must be either 0x0800 or 0x86dd.
+         *   OXM_OF_IP_PROTO must match 6 exactly.
+         *
+         * Format: 16-bit integer in network byte order.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_TCP_SRC    OXM_HEADER  (0x8000, OFPXMT_OFB_TCP_SRC, 2)
+        //#define OXM_OF_TCP_DST    OXM_HEADER  (0x8000, OFPXMT_OFB_TCP_DST, 2)
+        uint32 tcp_src = 16; /* Used for OFPXMT_OFB_TCP_SRC */
+        uint32 tcp_dst = 17; /* Used for OFPXMT_OFB_TCP_DST */
+
+        /* The source or destination port in the UDP header.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match either 0x0800 or 0x86dd.
+         *   OXM_OF_IP_PROTO must match 17 exactly.
+         *
+         * Format: 16-bit integer in network byte order.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_UDP_SRC    OXM_HEADER  (0x8000, OFPXMT_OFB_UDP_SRC, 2)
+        //#define OXM_OF_UDP_DST    OXM_HEADER  (0x8000, OFPXMT_OFB_UDP_DST, 2)
+        uint32 udp_src = 18; /* Used for OFPXMT_OFB_UDP_SRC */
+        uint32 udp_dst = 19; /* Used for OFPXMT_OFB_UDP_DST */
+
+        /* The source or destination port in the SCTP header.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match either 0x0800 or 0x86dd.
+         *   OXM_OF_IP_PROTO must match 132 exactly.
+         *
+         * Format: 16-bit integer in network byte order.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_SCTP_SRC   OXM_HEADER  (0x8000, OFPXMT_OFB_SCTP_SRC, 2)
+        //#define OXM_OF_SCTP_DST   OXM_HEADER  (0x8000, OFPXMT_OFB_SCTP_DST, 2)
+        uint32 sctp_src = 20; /* Used for OFPXMT_OFB_SCTP_SRC */
+        uint32 sctp_dst = 21; /* Used for OFPXMT_OFB_SCTP_DST */
+
+        /* The type or code in the ICMP header.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match 0x0800 exactly.
+         *   OXM_OF_IP_PROTO must match 1 exactly.
+         *
+         * Format: 8-bit integer.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_ICMPV4_TYPE  OXM_HEADER  (0x8000, OFPXMT_OFB_ICMPV4_TYPE, 1)
+        //#define OXM_OF_ICMPV4_CODE  OXM_HEADER  (0x8000, OFPXMT_OFB_ICMPV4_CODE, 1)
+        uint32 icmpv4_type = 22; /* Used for OFPXMT_OFB_ICMPV4_TYPE */
+        uint32 icmpv4_code = 23; /* Used for OFPXMT_OFB_ICMPV4_CODE */
+
+        /* ARP opcode.
+         *
+         * For an Ethernet+IP ARP packet, the opcode in the ARP header.  Always 0
+         * otherwise.
+         *
+         * Prereqs: OXM_OF_ETH_TYPE must match 0x0806 exactly.
+         *
+         * Format: 16-bit integer in network byte order.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_ARP_OP     OXM_HEADER  (0x8000, OFPXMT_OFB_ARP_OP, 2)
+        uint32 arp_op = 24; /* Used for OFPXMT_OFB_ARP_OP */
+
+        /* For an Ethernet+IP ARP packet, the source or target protocol address
+         * in the ARP header.  Always 0 otherwise.
+         *
+         * Prereqs: OXM_OF_ETH_TYPE must match 0x0806 exactly.
+         *
+         * Format: 32-bit integer in network byte order.
+         *
+         * Masking: Arbitrary masks.
+         */
+        //#define OXM_OF_ARP_SPA    OXM_HEADER  (0x8000, OFPXMT_OFB_ARP_SPA, 4)
+        //#define OXM_OF_ARP_SPA_W  OXM_HEADER_W(0x8000, OFPXMT_OFB_ARP_SPA, 4)
+        //#define OXM_OF_ARP_TPA    OXM_HEADER  (0x8000, OFPXMT_OFB_ARP_TPA, 4)
+        //#define OXM_OF_ARP_TPA_W  OXM_HEADER_W(0x8000, OFPXMT_OFB_ARP_TPA, 4)
+        uint32 arp_spa = 25; /* For OFPXMT_OFB_ARP_SPA */
+        uint32 arp_tpa = 26; /* For OFPXMT_OFB_ARP_TPA */
+
+        /* For an Ethernet+IP ARP packet, the source or target hardware address
+         * in the ARP header.  Always 0 otherwise.
+         *
+         * Prereqs: OXM_OF_ETH_TYPE must match 0x0806 exactly.
+         *
+         * Format: 48-bit Ethernet MAC address.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_ARP_SHA    OXM_HEADER   (0x8000, OFPXMT_OFB_ARP_SHA, 6)
+        //#define OXM_OF_ARP_SHA_W  OXM_HEADER_W (0x8000, OFPXMT_OFB_ARP_SHA, 6)
+        //#define OXM_OF_ARP_THA    OXM_HEADER   (0x8000, OFPXMT_OFB_ARP_THA, 6)
+        //#define OXM_OF_ARP_THA_W  OXM_HEADER_W (0x8000, OFPXMT_OFB_ARP_THA, 6)
+        bytes arp_sha = 27; /* For OFPXMT_OFB_ARP_SHA (6 bytes) */
+        bytes arp_tha = 28; /* For OFPXMT_OFB_ARP_THA (6 bytes) */
+
+        /* The source or destination address in the IPv6 header.
+         *
+         * Prereqs: OXM_OF_ETH_TYPE must match 0x86dd exactly.
+         *
+         * Format: 128-bit IPv6 address.
+         *
+         * Masking: Arbitrary masks.
+         */
+        //#define OXM_OF_IPV6_SRC    OXM_HEADER  (0x8000, OFPXMT_OFB_IPV6_SRC, 16)
+        //#define OXM_OF_IPV6_SRC_W  OXM_HEADER_W(0x8000, OFPXMT_OFB_IPV6_SRC, 16)
+        //#define OXM_OF_IPV6_DST    OXM_HEADER  (0x8000, OFPXMT_OFB_IPV6_DST, 16)
+        //#define OXM_OF_IPV6_DST_W  OXM_HEADER_W(0x8000, OFPXMT_OFB_IPV6_DST, 16)
+        bytes ipv6_src = 29; /* For OFPXMT_OFB_IPV6_SRC */
+        bytes ipv6_dst = 30; /* For OFPXMT_OFB_IPV6_DST */
+
+        /* The IPv6 Flow Label
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match 0x86dd exactly
+         *
+         * Format: 32-bit integer with 12 most-significant bits forced to 0.
+         * Only the lower 20 bits have meaning.
+         *
+         * Masking: Arbitrary masks.
+         */
+        //#define OXM_OF_IPV6_FLABEL   OXM_HEADER  (0x8000, OFPXMT_OFB_IPV6_FLABEL, 4)
+        //#define OXM_OF_IPV6_FLABEL_W OXM_HEADER_W(0x8000, OFPXMT_OFB_IPV6_FLABEL, 4)
+        uint32 ipv6_flabel = 31; /* For OFPXMT_OFB_IPV6_FLABEL */
+
+        /* The type or code in the ICMPv6 header.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match 0x86dd exactly.
+         *   OXM_OF_IP_PROTO must match 58 exactly.
+         *
+         * Format: 8-bit integer.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_ICMPV6_TYPE OXM_HEADER  (0x8000, OFPXMT_OFB_ICMPV6_TYPE, 1)
+        //#define OXM_OF_ICMPV6_CODE OXM_HEADER  (0x8000, OFPXMT_OFB_ICMPV6_CODE, 1)
+        uint32 icmpv6_type = 32; /* For OFPXMT_OFB_ICMPV6_TYPE */
+        uint32 icmpv6_code = 33; /* For OFPXMT_OFB_ICMPV6_CODE */
+
+        /* The target address in an IPv6 Neighbor Discovery message.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match 0x86dd exactly.
+         *   OXM_OF_IP_PROTO must match 58 exactly.
+         *   OXM_OF_ICMPV6_TYPE must be either 135 or 136.
+         *
+         * Format: 128-bit IPv6 address.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_IPV6_ND_TARGET OXM_HEADER \
+        //    (0x8000, OFPXMT_OFB_IPV6_ND_TARGET, 16)
+        bytes ipv6_nd_target = 34; /* For OFPXMT_OFB_IPV6_ND_TARGET */
+
+        /* The source link-layer address option in an IPv6 Neighbor Discovery
+         * message.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match 0x86dd exactly.
+         *   OXM_OF_IP_PROTO must match 58 exactly.
+         *   OXM_OF_ICMPV6_TYPE must be exactly 135.
+         *
+         * Format: 48-bit Ethernet MAC address.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_IPV6_ND_SLL  OXM_HEADER  (0x8000, OFPXMT_OFB_IPV6_ND_SLL, 6)
+        bytes ipv6_nd_ssl = 35; /* For OFPXMT_OFB_IPV6_ND_SLL */
+
+        /* The target link-layer address option in an IPv6 Neighbor Discovery
+         * message.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match 0x86dd exactly.
+         *   OXM_OF_IP_PROTO must match 58 exactly.
+         *   OXM_OF_ICMPV6_TYPE must be exactly 136.
+         *
+         * Format: 48-bit Ethernet MAC address.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_IPV6_ND_TLL  OXM_HEADER  (0x8000, OFPXMT_OFB_IPV6_ND_TLL, 6)
+        bytes ipv6_nd_tll = 36; /* For OFPXMT_OFB_IPV6_ND_TLL */
+
+        /* The LABEL in the first MPLS shim header.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match 0x8847 or 0x8848 exactly.
+         *
+         * Format: 32-bit integer in network byte order with 12 most-significant
+         * bits forced to 0. Only the lower 20 bits have meaning.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_MPLS_LABEL  OXM_HEADER  (0x8000, OFPXMT_OFB_MPLS_LABEL, 4)
+        uint32 mpls_label = 37; /* For OFPXMT_OFB_MPLS_LABEL */
+
+        /* The TC in the first MPLS shim header.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match 0x8847 or 0x8848 exactly.
+         *
+         * Format: 8-bit integer with 5 most-significant bits forced to 0.
+         * Only the lower 3 bits have meaning.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_MPLS_TC     OXM_HEADER  (0x8000, OFPXMT_OFB_MPLS_TC, 1)
+        uint32 mpls_tc = 38; /* For OFPXMT_OFB_MPLS_TC */
+
+        /* The BoS bit in the first MPLS shim header.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match 0x8847 or 0x8848 exactly.
+         *
+         * Format: 8-bit integer with 7 most-significant bits forced to 0.
+         * Only the lowest bit have a meaning.
+         *
+         * Masking: Not maskable. */
+        //#define OXM_OF_MPLS_BOS     OXM_HEADER  (0x8000, OFPXMT_OFB_MPLS_BOS, 1)
+        uint32 mpls_bos = 39; /* For OFPXMT_OFB_MPLS_BOS */
+
+        /* IEEE 802.1ah I-SID.
+         *
+         * For a packet with a PBB header, this is the I-SID from the
+         * outermost service tag.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match 0x88E7 exactly.
+         *
+         * Format: 24-bit integer in network byte order.
+         *
+         * Masking: Arbitrary masks. */
+        //#define OXM_OF_PBB_ISID   OXM_HEADER  (0x8000, OFPXMT_OFB_PBB_ISID, 3)
+        //#define OXM_OF_PBB_ISID_W OXM_HEADER_W(0x8000, OFPXMT_OFB_PBB_ISID, 3)
+        uint32 pbb_isid = 40; /* For OFPXMT_OFB_PBB_ISID */
+
+        /* Logical Port Metadata.
+         *
+         * Metadata associated with a logical port.
+         * If the logical port performs encapsulation and decapsulation, this
+         * is the demultiplexing field from the encapsulation header.
+         * For example, for a packet received via GRE tunnel including a (32-bit) key,
+         * the key is stored in the low 32-bits and the high bits are zeroed.
+         * For a MPLS logical port, the low 20 bits represent the MPLS Label.
+         * For a VxLAN logical port, the low 24 bits represent the VNI.
+         * If the packet is not received through a logical port, the value is 0.
+         *
+         * Prereqs: None.
+         *
+         * Format: 64-bit integer in network byte order.
+         *
+         * Masking: Arbitrary masks. */
+        //#define OXM_OF_TUNNEL_ID    OXM_HEADER  (0x8000, OFPXMT_OFB_TUNNEL_ID, 8)
+        //#define OXM_OF_TUNNEL_ID_W  OXM_HEADER_W(0x8000, OFPXMT_OFB_TUNNEL_ID, 8)
+        uint64 tunnel_id = 41; /* For OFPXMT_OFB_TUNNEL_ID */
+
+        /* The IPv6 Extension Header pseudo-field.
+         *
+         * Prereqs:
+         *   OXM_OF_ETH_TYPE must match 0x86dd exactly
+         *
+         * Format: 16-bit integer with 7 most-significant bits forced to 0.
+         * Only the lower 9 bits have meaning.
+         *
+         * Masking: Maskable. */
+        //#define OXM_OF_IPV6_EXTHDR   OXM_HEADER  (0x8000, OFPXMT_OFB_IPV6_EXTHDR, 2)
+        //#define OXM_OF_IPV6_EXTHDR_W OXM_HEADER_W(0x8000, OFPXMT_OFB_IPV6_EXTHDR, 2)
+        uint32 ipv6_exthdr = 42; /* For OFPXMT_OFB_IPV6_EXTHDR */
+
+    }
+
+    /* Optional mask values (must be present when has_mask is true */
+    oneof mask {
+        uint64 table_metadata_mask = 105; /* For OFPXMT_OFB_METADATA */
+
+        bytes eth_dst_mask = 106; /* For OFPXMT_OFB_ETH_DST (exactly 6 bytes)*/
+        bytes eth_src_mask = 107; /* For OFPXMT_OFB_ETH_SRC (exactly 6 bytes)*/
+
+        uint32 vlan_vid_mask = 109; /* For OFPXMT_OFB_VLAN_VID */
+
+        uint32 ipv4_src_mask = 114; /* For OFPXMT_OFB_IPV4_SRC */
+        uint32 ipv4_dst_mask = 115; /* For OFPXMT_OFB_IPV4_DST */
+
+        uint32 arp_spa_mask = 125; /* For OFPXMT_OFB_ARP_SPA */
+        uint32 arp_tpa_mask = 126; /* For OFPXMT_OFB_ARP_TPA */
+
+        bytes ipv6_src_mask = 129; /* For OFPXMT_OFB_IPV6_SRC */
+        bytes ipv6_dst_mask = 130; /* For OFPXMT_OFB_IPV6_DST */
+
+        uint32 ipv6_flabel_mask = 131; /* For OFPXMT_OFB_IPV6_FLABEL */
+
+        uint32 pbb_isid_mask = 140; /* For OFPXMT_OFB_PBB_ISID */
+
+        uint64 tunnel_id_mask = 141; /* For OFPXMT_OFB_TUNNEL_ID */
+
+        uint32 ipv6_exthdr_mask = 142; /* For OFPXMT_OFB_IPV6_EXTHDR */
+    }
+
+}
+//#define OFPXMT_OFB_ALL    ((UINT64_C(1) << 40) - 1)
+
+
+/* The VLAN id is 12-bits, so we can use the entire 16 bits to indicate
+ * special conditions.
+ */
+enum ofp_vlan_id {
+    OFPVID_NONE    = 0x0000; /* No VLAN id was set. */
+    OFPVID_PRESENT = 0x1000; /* Bit that indicate that a VLAN id is set */
+};
+/* Define for compatibility */
+//#define OFP_VLAN_NONE      OFPVID_NONE
+
+/* Bit definitions for IPv6 Extension Header pseudo-field. */
+enum ofp_ipv6exthdr_flags {
+    OFPIEH_INVALID = 0;
+    OFPIEH_NONEXT  = 1;     /* "No next header" encountered. */
+    OFPIEH_ESP     = 2;     /* Encrypted Sec Payload header present. */
+    OFPIEH_AUTH    = 4;     /* Authentication header present. */
+    OFPIEH_DEST    = 8;     /* 1 or 2 dest headers present. */
+    OFPIEH_FRAG    = 16;    /* Fragment header present. */
+    OFPIEH_ROUTER  = 32;    /* Router header present. */
+    OFPIEH_HOP     = 64;    /* Hop-by-hop header present. */
+    OFPIEH_UNREP   = 128;   /* Unexpected repeats encountered. */
+    OFPIEH_UNSEQ   = 256;   /* Unexpected sequencing encountered. */
+};
+
+/* Header for OXM experimenter match fields.
+ * The experimenter class should not use OXM_HEADER() macros for defining
+ * fields due to this extra header. */
+message ofp_oxm_experimenter_field {
+    uint32 oxm_header = 1;    /* oxm_class = OFPXMC_EXPERIMENTER */
+    uint32 experimenter = 2;  /* Experimenter ID which takes the same
+                                 form as in struct ofp_experimenter_header. */
+};
+
+/* ## ----------------- ## */
+/* ## OpenFlow Actions. ## */
+/* ## ----------------- ## */
+
+enum ofp_action_type {
+    OFPAT_OUTPUT       = 0;  /* Output to switch port. */
+    OFPAT_COPY_TTL_OUT = 11; /* Copy TTL "outwards" -- from next-to-outermost
+                                to outermost */
+    OFPAT_COPY_TTL_IN  = 12; /* Copy TTL "inwards" -- from outermost to
+                               next-to-outermost */
+    OFPAT_SET_MPLS_TTL = 15; /* MPLS TTL */
+    OFPAT_DEC_MPLS_TTL = 16; /* Decrement MPLS TTL */
+
+    OFPAT_PUSH_VLAN    = 17; /* Push a new VLAN tag */
+    OFPAT_POP_VLAN     = 18; /* Pop the outer VLAN tag */
+    OFPAT_PUSH_MPLS    = 19; /* Push a new MPLS tag */
+    OFPAT_POP_MPLS     = 20; /* Pop the outer MPLS tag */
+    OFPAT_SET_QUEUE    = 21; /* Set queue id when outputting to a port */
+    OFPAT_GROUP        = 22; /* Apply group. */
+    OFPAT_SET_NW_TTL   = 23; /* IP TTL. */
+    OFPAT_DEC_NW_TTL   = 24; /* Decrement IP TTL. */
+    OFPAT_SET_FIELD    = 25; /* Set a header field using OXM TLV format. */
+    OFPAT_PUSH_PBB     = 26; /* Push a new PBB service tag (I-TAG) */
+    OFPAT_POP_PBB      = 27; /* Pop the outer PBB service tag (I-TAG) */
+    OFPAT_EXPERIMENTER = 0xffff;
+};
+
+/* Action header that is common to all actions.  The length includes the
+ * header and any padding used to make the action 64-bit aligned.
+ * NB: The length of an action *must* always be a multiple of eight. */
+message ofp_action {
+    ofp_action_type type = 1;       /* One of OFPAT_*. */
+    oneof action {
+        ofp_action_output output = 2;
+        ofp_action_mpls_ttl mpls_ttl = 3;
+        ofp_action_push push = 4;
+        ofp_action_pop_mpls pop_mpls = 5;
+        ofp_action_group group = 6;
+        ofp_action_nw_ttl nw_ttl = 7;
+        ofp_action_set_field set_field = 8;
+        ofp_action_experimenter experimenter = 9;
+    }
+};
+
+enum ofp_controller_max_len {
+    OFPCML_INVALID   = 0;
+    OFPCML_MAX       = 0xffe5; /* maximum max_len value which can be used
+                                  to request a specific byte length. */
+    OFPCML_NO_BUFFER = 0xffff; /* indicates that no buffering should be
+                                  applied and the whole packet is to be
+                                  sent to the controller. */
+};
+
+/* Action structure for OFPAT_OUTPUT, which sends packets out 'port'.
+ * When the 'port' is the OFPP_CONTROLLER, 'max_len' indicates the max
+ * number of bytes to send.  A 'max_len' of zero means no bytes of the
+ * packet should be sent. A 'max_len' of OFPCML_NO_BUFFER means that
+ * the packet is not buffered and the complete packet is to be sent to
+ * the controller. */
+message ofp_action_output {
+    uint32 port = 1;                 /* Output port. */
+    uint32 max_len = 2;              /* Max length to send to controller. */
+};
+
+/* Action structure for OFPAT_SET_MPLS_TTL. */
+message ofp_action_mpls_ttl {
+    uint32 mpls_ttl = 1;             /* MPLS TTL */
+};
+
+/* Action structure for OFPAT_PUSH_VLAN/MPLS/PBB. */
+message ofp_action_push {
+    uint32 ethertype = 1;            /* Ethertype */
+};
+
+/* Action structure for OFPAT_POP_MPLS. */
+message ofp_action_pop_mpls {
+    uint32 ethertype = 1;            /* Ethertype */
+};
+
+/* Action structure for OFPAT_GROUP. */
+message ofp_action_group {
+    uint32 group_id = 1;             /* Group identifier. */
+};
+
+/* Action structure for OFPAT_SET_NW_TTL. */
+message ofp_action_nw_ttl {
+    uint32 nw_ttl = 1;               /* IP TTL */
+};
+
+/* Action structure for OFPAT_SET_FIELD. */
+message ofp_action_set_field {
+    ofp_oxm_field field = 1;
+};
+
+/* Action header for OFPAT_EXPERIMENTER.
+ * The rest of the body is experimenter-defined. */
+message ofp_action_experimenter {
+    uint32 experimenter = 1;         /* Experimenter ID which takes the same
+                                        form as in struct
+                                        ofp_experimenter_header. */
+    bytes data = 2;
+};
+
+/* ## ---------------------- ## */
+/* ## OpenFlow Instructions. ## */
+/* ## ---------------------- ## */
+
+enum ofp_instruction_type {
+    OFPIT_INVALID    = 0;
+    OFPIT_GOTO_TABLE = 1;       /* Setup the next table in the lookup
+                                   pipeline */
+    OFPIT_WRITE_METADATA = 2;   /* Setup the metadata field for use later in
+                                   pipeline */
+    OFPIT_WRITE_ACTIONS = 3;    /* Write the action(s) onto the datapath action
+                                   set */
+    OFPIT_APPLY_ACTIONS = 4;    /* Applies the action(s) immediately */
+    OFPIT_CLEAR_ACTIONS = 5;    /* Clears all actions from the datapath
+                                   action set */
+    OFPIT_METER = 6;            /* Apply meter (rate limiter) */
+
+    OFPIT_EXPERIMENTER = 0xFFFF; /* Experimenter instruction */
+};
+
+/* Instruction header that is common to all instructions.  The length includes
+ * the header and any padding used to make the instruction 64-bit aligned.
+ * NB: The length of an instruction *must* always be a multiple of eight. */
+message ofp_instruction {
+    uint32 type = 1;               /* Instruction type */
+    oneof data {
+        ofp_instruction_goto_table goto_table = 2;
+        ofp_instruction_write_metadata write_metadata = 3;
+        ofp_instruction_actions actions = 4;
+        ofp_instruction_meter meter = 5;
+        ofp_instruction_experimenter experimenter = 6;
+    }
+};
+
+/* Instruction structure for OFPIT_GOTO_TABLE */
+message ofp_instruction_goto_table {
+    uint32 table_id = 1;           /* Set next table in the lookup pipeline */
+};
+
+/* Instruction structure for OFPIT_WRITE_METADATA */
+message ofp_instruction_write_metadata {
+    uint64 metadata = 1;           /* Metadata value to write */
+    uint64 metadata_mask = 2;      /* Metadata write bitmask */
+};
+
+/* Instruction structure for OFPIT_WRITE/APPLY/CLEAR_ACTIONS */
+message ofp_instruction_actions {
+    repeated ofp_action actions = 1; /* 0 or more actions associated
+                                        with OFPIT_WRITE_ACTIONS and
+                                        OFPIT_APPLY_ACTIONS */
+};
+
+/* Instruction structure for OFPIT_METER */
+message ofp_instruction_meter {
+    uint32 meter_id = 1;           /* Meter instance. */
+};
+
+/* Instruction structure for experimental instructions */
+message ofp_instruction_experimenter {
+    uint32 experimenter = 1;     /* Experimenter ID which takes the same form
+                                   as in struct ofp_experimenter_header. */
+    /* Experimenter-defined arbitrary additional data. */
+    bytes data = 2;
+};
+
+/* ## --------------------------- ## */
+/* ## OpenFlow Flow Modification. ## */
+/* ## --------------------------- ## */
+
+enum ofp_flow_mod_command {
+    OFPFC_ADD           = 0; /* New flow. */
+    OFPFC_MODIFY        = 1; /* Modify all matching flows. */
+    OFPFC_MODIFY_STRICT = 2; /* Modify entry strictly matching wildcards and
+                                priority. */
+    OFPFC_DELETE        = 3; /* Delete all matching flows. */
+    OFPFC_DELETE_STRICT = 4; /* Delete entry strictly matching wildcards and
+                                priority. */
+};
+
+/* Value used in "idle_timeout" and "hard_timeout" to indicate that the entry
+ * is permanent. */
+//#define OFP_FLOW_PERMANENT 0
+
+/* By default, choose a priority in the middle. */
+//#define OFP_DEFAULT_PRIORITY 0x8000
+
+enum ofp_flow_mod_flags {
+    OFPFF_INVALID       = 0;
+    OFPFF_SEND_FLOW_REM = 1;  /* Send flow removed message when flow
+                               * expires or is deleted. */
+    OFPFF_CHECK_OVERLAP = 2;  /* Check for overlapping entries first. */
+    OFPFF_RESET_COUNTS  = 4;  /* Reset flow packet and byte counts. */
+    OFPFF_NO_PKT_COUNTS = 8;  /* Don't keep track of packet count. */
+    OFPFF_NO_BYT_COUNTS = 16; /* Don't keep track of byte count. */
+};
+
+/* Flow setup and teardown (controller -> datapath). */
+message ofp_flow_mod {
+    //ofp_header header;
+    uint64 cookie = 1;             /* Opaque controller-issued identifier. */
+    uint64 cookie_mask = 2;        /* Mask used to restrict the cookie bits
+                                      that must match when the command is
+                                      OFPFC_MODIFY* or OFPFC_DELETE*. A value
+                                      of 0 indicates no restriction. */
+    uint32 table_id = 3;           /* ID of the table to put the flow in.
+                                      For OFPFC_DELETE_* commands, OFPTT_ALL
+                                      can also be used to delete matching
+                                      flows from all tables. */
+    ofp_flow_mod_command command = 4; /* One of OFPFC_*. */
+    uint32 idle_timeout = 5;       /* Idle time before discarding (seconds). */
+    uint32 hard_timeout = 6;       /* Max time before discarding (seconds). */
+    uint32 priority = 7;           /* Priority level of flow entry. */
+    uint32 buffer_id = 8;          /* Buffered packet to apply to, or
+                                      OFP_NO_BUFFER.
+                                      Not meaningful for OFPFC_DELETE*. */
+    uint32 out_port = 9;          /* For OFPFC_DELETE* commands, require
+                                      matching entries to include this as an
+                                      output port.  A value of OFPP_ANY
+                                      indicates no restriction. */
+    uint32 out_group = 10;         /* For OFPFC_DELETE* commands, require
+                                      matching entries to include this as an
+                                      output group.  A value of OFPG_ANY
+                                      indicates no restriction. */
+    uint32 flags = 11;             /* Bitmap of OFPFF_* flags. */
+    ofp_match match = 12;          /* Fields to match. Variable size. */
+    repeated ofp_instruction instructions = 13; /* 0 or more. */
+};
+
+/* Group numbering. Groups can use any number up to OFPG_MAX. */
+enum ofp_group {
+
+    OFPG_INVALID = 0;
+
+    /* Last usable group number. */
+    OFPG_MAX        = 0x7fffff00;
+
+    /* Fake groups. */
+    OFPG_ALL        = 0x7ffffffc;  /* Represents all groups for group delete
+                                      commands. */
+    OFPG_ANY        = 0x7fffffff;  /* Special wildcard: no group specified. */
+};
+
+/* Group commands */
+enum ofp_group_mod_command {
+    OFPGC_ADD    = 0;       /* New group. */
+    OFPGC_MODIFY = 1;       /* Modify all matching groups. */
+    OFPGC_DELETE = 2;       /* Delete all matching groups. */
+};
+
+/* Bucket for use in groups. */
+message ofp_bucket {
+    uint32 weight = 1;              /* Relative weight of bucket.  Only
+                                       defined for select groups. */
+    uint32 watch_port = 2;          /* Port whose state affects whether this
+                                       bucket is live.  Only required for fast
+                                       failover groups. */
+    uint32 watch_group = 3;         /* Group whose state affects whether this
+                                       bucket is live.  Only required for fast
+                                       failover groups. */
+    repeated ofp_action actions = 4;
+};
+
+/* Group setup and teardown (controller -> datapath). */
+message ofp_group_mod {
+    //ofp_header header;
+    ofp_group_mod_command command = 1; /* One of OFPGC_*. */
+    ofp_group_type type = 2;           /* One of OFPGT_*. */
+    uint32 group_id = 3;               /* Group identifier. */
+    repeated ofp_bucket buckets = 4;
+};
+
+/* Group types.  Values in the range [128; 255] are reserved for experimental
+ * use. */
+enum ofp_group_type {
+    OFPGT_ALL      = 0; /* All (multicast/broadcast) group.  */
+    OFPGT_SELECT   = 1; /* Select group. */
+    OFPGT_INDIRECT = 2; /* Indirect group. */
+    OFPGT_FF       = 3; /* Fast failover group. */
+};
+
+/* Special buffer-id to indicate 'no buffer' */
+//#define OFP_NO_BUFFER 0xffffffff
+
+/* Send packet (controller -> datapath). */
+message ofp_packet_out {
+    //ofp_header header;
+    uint32 buffer_id = 1;          /* ID assigned by datapath (OFP_NO_BUFFER
+                                      if none). */
+    uint32 in_port = 2;            /* Packet's input port or OFPP_CONTROLLER.*/
+    repeated ofp_action actions = 3; /* Action list - 0 or more. */
+    /* The variable size action list is optionally followed by packet data.
+     * This data is only present and meaningful if buffer_id == -1. */
+    bytes data = 4;                /* Packet data. */
+};
+
+/* Why is this packet being sent to the controller? */
+enum ofp_packet_in_reason {
+    OFPR_NO_MATCH    = 0;   /* No matching flow (table-miss flow entry). */
+    OFPR_ACTION      = 1;   /* Action explicitly output to controller. */
+    OFPR_INVALID_TTL = 2;   /* Packet has invalid TTL */
+};
+
+/* Packet received on port (datapath -> controller). */
+message ofp_packet_in {
+    //ofp_header header;
+    uint32 buffer_id = 1;     /* ID assigned by datapath. */
+    ofp_packet_in_reason reason = 2; /* Reason packet is being sent */
+    uint32 table_id = 3;      /* ID of the table that was looked up */
+    uint64 cookie = 4;        /* Cookie of the flow entry that was looked up. */
+    ofp_match match = 5;      /* Packet metadata. Variable size. */
+    bytes data = 6;           /* Ethernet frame */
+};
+
+/* Why was this flow removed? */
+enum ofp_flow_removed_reason {
+    OFPRR_IDLE_TIMEOUT = 0;     /* Flow idle time exceeded idle_timeout. */
+    OFPRR_HARD_TIMEOUT = 1;     /* Time exceeded hard_timeout. */
+    OFPRR_DELETE       = 2;     /* Evicted by a DELETE flow mod. */
+    OFPRR_GROUP_DELETE = 3;     /* Group was removed. */
+    OFPRR_METER_DELETE = 4;     /* Meter was removed */
+};
+
+/* Flow removed (datapath -> controller). */
+message ofp_flow_removed {
+    //ofp_header header;
+    uint64 cookie = 1;         /* Opaque controller-issued identifier. */
+
+    uint32 priority = 2;       /* Priority level of flow entry. */
+    ofp_flow_removed_reason reason = 3; /* One of OFPRR_*. */
+    uint32 table_id = 4;        /* ID of the table */
+
+    uint32 duration_sec = 5;   /* Time flow was alive in seconds. */
+    uint32 duration_nsec = 6;  /* Time flow was alive in nanoseconds beyond
+                                 duration_sec. */
+    uint32 idle_timeout = 7;   /* Idle timeout from original flow mod. */
+    uint32 hard_timeout = 8;   /* Hard timeout from original flow mod. */
+    uint64 packet_count = 9;
+    uint64 byte_count = 10;
+    ofp_match match = 121;  /* Description of fields. Variable size. */
+};
+
+/* Meter numbering. Flow meters can use any number up to OFPM_MAX. */
+enum ofp_meter {
+    OFPM_ZERO       = 0;
+    /* Last usable meter. */
+    OFPM_MAX        = 0x7fff0000;
+
+    /* Virtual meters. */
+    OFPM_SLOWPATH   = 0x7ffffffd;  /* Meter for slow datapath. */
+    OFPM_CONTROLLER = 0x7ffffffe;  /* Meter for controller connection. */
+    OFPM_ALL        = 0x7fffffff;  /* Represents all meters for stat requests
+                                      commands. */
+};
+
+/* Meter band types */
+enum ofp_meter_band_type {
+    OFPMBT_INVALID         = 0;
+    OFPMBT_DROP            = 1;      /* Drop packet. */
+    OFPMBT_DSCP_REMARK     = 2;      /* Remark DSCP in the IP header. */
+    OFPMBT_EXPERIMENTER    = 0xFFFF; /* Experimenter meter band. */
+};
+
+/* Common header for all meter bands */
+message ofp_meter_band_header {
+    ofp_meter_band_type type = 1;   /* One of OFPMBT_*. */
+    uint32              len = 2;    /* Length in bytes of this band. */
+    uint32              rate = 3;   /* Rate for this band. */
+    uint32              burst_size = 4;/* Size of bursts. */
+};
+
+/* OFPMBT_DROP band - drop packets */
+message ofp_meter_band_drop {
+    uint32        type = 1;   /* OFPMBT_DROP. */
+    uint32        len = 2;   /* Length in bytes of this band. */
+    uint32        rate = 3;   /* Rate for dropping packets. */
+    uint32        burst_size = 4;/* Size of bursts. */
+};
+
+/* OFPMBT_DSCP_REMARK band - Remark DSCP in the IP header */
+message ofp_meter_band_dscp_remark {
+    uint32        type = 1;       /* OFPMBT_DSCP_REMARK. */
+    uint32        len = 2;        /* Length in bytes of this band. */
+    uint32        rate = 3;       /* Rate for remarking packets. */
+    uint32        burst_size = 4; /* Size of bursts. */
+    uint32        prec_level = 5; /* Number of drop precedence level to add. */
+};
+
+/* OFPMBT_EXPERIMENTER band - Experimenter type.
+ * The rest of the band is experimenter-defined. */
+message ofp_meter_band_experimenter {
+    ofp_meter_band_type type = 1;        /* One of OFPMBT_*. */
+    uint32              len = 2;         /* Length in bytes of this band. */
+    uint32              rate = 3;        /* Rate for this band. */
+    uint32              burst_size = 4;  /* Size of bursts. */
+    uint32              experimenter = 5;/* Experimenter ID which takes the
+                                            same form as in struct
+                                            ofp_experimenter_header. */
+};
+
+/* Meter commands */
+enum ofp_meter_mod_command {
+    OFPMC_ADD = 0;              /* New meter. */
+    OFPMC_MODIFY = 1;           /* Modify specified meter. */
+    OFPMC_DELETE = 2;           /* Delete specified meter. */
+};
+
+/* Meter configuration flags */
+enum ofp_meter_flags {
+    OFPMF_INVALID = 0;
+    OFPMF_KBPS    = 1;     /* Rate value in kb/s (kilo-bit per second). */
+    OFPMF_PKTPS   = 2;     /* Rate value in packet/sec. */
+    OFPMF_BURST   = 4;     /* Do burst size. */
+    OFPMF_STATS   = 8;     /* Collect statistics. */
+};
+
+/* Meter configuration. OFPT_METER_MOD. */
+message ofp_meter_mod {
+//    ofp_header   header = 1;
+    ofp_meter_mod_command command = 1;       /* One of OFPMC_*. */
+    uint32                flags = 2;         /* Bitmap of OFPMF_* flags. */
+    uint32                meter_id = 3;      /* Meter instance. */
+    repeated ofp_meter_band_header bands = 4; /* The band list length is
+                                                 inferred from the length field
+                                                 in the header. */
+};
+
+/* Values for 'type' in ofp_error_message.  These values are immutable: they
+ * will not change in future versions of the protocol (although new values may
+ * be added). */
+enum ofp_error_type {
+    OFPET_HELLO_FAILED         = 0;  /* Hello protocol failed. */
+    OFPET_BAD_REQUEST          = 1;  /* Request was not understood. */
+    OFPET_BAD_ACTION           = 2;  /* Error in action description. */
+    OFPET_BAD_INSTRUCTION      = 3;  /* Error in instruction list. */
+    OFPET_BAD_MATCH            = 4;  /* Error in match. */
+    OFPET_FLOW_MOD_FAILED      = 5;  /* Problem modifying flow entry. */
+    OFPET_GROUP_MOD_FAILED     = 6;  /* Problem modifying group entry. */
+    OFPET_PORT_MOD_FAILED      = 7;  /* Port mod request failed. */
+    OFPET_TABLE_MOD_FAILED     = 8;  /* Table mod request failed. */
+    OFPET_QUEUE_OP_FAILED      = 9;  /* Queue operation failed. */
+    OFPET_SWITCH_CONFIG_FAILED = 10; /* Switch config request failed. */
+    OFPET_ROLE_REQUEST_FAILED  = 11; /* Controller Role request failed. */
+    OFPET_METER_MOD_FAILED     = 12; /* Error in meter. */
+    OFPET_TABLE_FEATURES_FAILED = 13; /* Setting table features failed. */
+    OFPET_EXPERIMENTER = 0xffff;      /* Experimenter error messages. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_HELLO_FAILED.  'data' contains an
+ * ASCII text string that may give failure details. */
+enum ofp_hello_failed_code {
+    OFPHFC_INCOMPATIBLE = 0;    /* No compatible version. */
+    OFPHFC_EPERM        = 1;    /* Permissions error. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_BAD_REQUEST.  'data' contains at least
+ * the first 64 bytes of the failed request. */
+enum ofp_bad_request_code {
+    OFPBRC_BAD_VERSION      = 0;  /* ofp_header.version not supported. */
+    OFPBRC_BAD_TYPE         = 1;  /* ofp_header.type not supported. */
+    OFPBRC_BAD_MULTIPART    = 2;  /* ofp_multipart_request.type not supported.
+                                   */
+    OFPBRC_BAD_EXPERIMENTER = 3;  /* Experimenter id not supported
+                                   * (in ofp_experimenter_header or
+                                   * ofp_multipart_request or
+                                   * ofp_multipart_reply). */
+    OFPBRC_BAD_EXP_TYPE     = 4;  /* Experimenter type not supported. */
+    OFPBRC_EPERM            = 5;  /* Permissions error. */
+    OFPBRC_BAD_LEN          = 6;  /* Wrong request length for type. */
+    OFPBRC_BUFFER_EMPTY     = 7;  /* Specified buffer has already been used. */
+    OFPBRC_BUFFER_UNKNOWN   = 8;  /* Specified buffer does not exist. */
+    OFPBRC_BAD_TABLE_ID     = 9;  /* Specified table-id invalid or does not
+                                   * exist. */
+    OFPBRC_IS_SLAVE         = 10; /* Denied because controller is slave. */
+    OFPBRC_BAD_PORT         = 11; /* Invalid port. */
+    OFPBRC_BAD_PACKET       = 12; /* Invalid packet in packet-out. */
+    OFPBRC_MULTIPART_BUFFER_OVERFLOW    = 13; /* ofp_multipart_request
+                                     overflowed the assigned buffer. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_BAD_ACTION.  'data' contains at least
+ * the first 64 bytes of the failed request. */
+enum ofp_bad_action_code {
+    OFPBAC_BAD_TYPE           = 0;  /* Unknown or unsupported action type. */
+    OFPBAC_BAD_LEN            = 1;  /* Length problem in actions. */
+    OFPBAC_BAD_EXPERIMENTER   = 2;  /* Unknown experimenter id specified. */
+    OFPBAC_BAD_EXP_TYPE       = 3;  /* Unknown action for experimenter id. */
+    OFPBAC_BAD_OUT_PORT       = 4;  /* Problem validating output port. */
+    OFPBAC_BAD_ARGUMENT       = 5;  /* Bad action argument. */
+    OFPBAC_EPERM              = 6;  /* Permissions error. */
+    OFPBAC_TOO_MANY           = 7;  /* Can't handle this many actions. */
+    OFPBAC_BAD_QUEUE          = 8;  /* Problem validating output queue. */
+    OFPBAC_BAD_OUT_GROUP      = 9;  /* Invalid group id in forward action. */
+    OFPBAC_MATCH_INCONSISTENT = 10; /* Action can't apply for this match,
+                                       or Set-Field missing prerequisite. */
+    OFPBAC_UNSUPPORTED_ORDER  = 11; /* Action order is unsupported for the
+                                 action list in an Apply-Actions instruction */
+    OFPBAC_BAD_TAG            = 12; /* Actions uses an unsupported
+                                       tag/encap. */
+    OFPBAC_BAD_SET_TYPE       = 13; /* Unsupported type in SET_FIELD action. */
+    OFPBAC_BAD_SET_LEN        = 14; /* Length problem in SET_FIELD action. */
+    OFPBAC_BAD_SET_ARGUMENT   = 15; /* Bad argument in SET_FIELD action. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_BAD_INSTRUCTION.  'data' contains at
+ * least the first 64 bytes of the failed request. */
+enum ofp_bad_instruction_code {
+    OFPBIC_UNKNOWN_INST     = 0; /* Unknown instruction. */
+    OFPBIC_UNSUP_INST       = 1; /* Switch or table does not support the
+                                    instruction. */
+    OFPBIC_BAD_TABLE_ID     = 2; /* Invalid Table-ID specified. */
+    OFPBIC_UNSUP_METADATA   = 3; /* Metadata value unsupported by datapath. */
+    OFPBIC_UNSUP_METADATA_MASK = 4; /* Metadata mask value unsupported by
+                                       datapath. */
+    OFPBIC_BAD_EXPERIMENTER = 5; /* Unknown experimenter id specified. */
+    OFPBIC_BAD_EXP_TYPE     = 6; /* Unknown instruction for experimenter id. */
+    OFPBIC_BAD_LEN          = 7; /* Length problem in instructions. */
+    OFPBIC_EPERM            = 8; /* Permissions error. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_BAD_MATCH.  'data' contains at least
+ * the first 64 bytes of the failed request. */
+enum ofp_bad_match_code {
+    OFPBMC_BAD_TYPE         = 0;  /* Unsupported match type specified by the
+                                     match */
+    OFPBMC_BAD_LEN          = 1;  /* Length problem in match. */
+    OFPBMC_BAD_TAG          = 2;  /* Match uses an unsupported tag/encap. */
+    OFPBMC_BAD_DL_ADDR_MASK = 3;  /* Unsupported datalink addr mask - switch
+                                     does not support arbitrary datalink
+                                     address mask. */
+    OFPBMC_BAD_NW_ADDR_MASK = 4;  /* Unsupported network addr mask - switch
+                                     does not support arbitrary network
+                                     address mask. */
+    OFPBMC_BAD_WILDCARDS    = 5;  /* Unsupported combination of fields masked
+                                     or omitted in the match. */
+    OFPBMC_BAD_FIELD        = 6;  /* Unsupported field type in the match. */
+    OFPBMC_BAD_VALUE        = 7;  /* Unsupported value in a match field. */
+    OFPBMC_BAD_MASK         = 8;  /* Unsupported mask specified in the match,
+                                     field is not dl-address or nw-address. */
+    OFPBMC_BAD_PREREQ       = 9;  /* A prerequisite was not met. */
+    OFPBMC_DUP_FIELD        = 10; /* A field type was duplicated. */
+    OFPBMC_EPERM            = 11; /* Permissions error. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_FLOW_MOD_FAILED.  'data' contains
+ * at least the first 64 bytes of the failed request. */
+enum ofp_flow_mod_failed_code {
+    OFPFMFC_UNKNOWN      = 0;   /* Unspecified error. */
+    OFPFMFC_TABLE_FULL   = 1;   /* Flow not added because table was full. */
+    OFPFMFC_BAD_TABLE_ID = 2;   /* Table does not exist */
+    OFPFMFC_OVERLAP      = 3;   /* Attempted to add overlapping flow with
+                                   CHECK_OVERLAP flag set. */
+    OFPFMFC_EPERM        = 4;   /* Permissions error. */
+    OFPFMFC_BAD_TIMEOUT  = 5;   /* Flow not added because of unsupported
+                                   idle/hard timeout. */
+    OFPFMFC_BAD_COMMAND  = 6;   /* Unsupported or unknown command. */
+    OFPFMFC_BAD_FLAGS    = 7;   /* Unsupported or unknown flags. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_GROUP_MOD_FAILED.  'data' contains
+ * at least the first 64 bytes of the failed request. */
+enum ofp_group_mod_failed_code {
+    OFPGMFC_GROUP_EXISTS         = 0;  /* Group not added because a group ADD
+                                          attempted to replace an
+                                          already-present group. */
+    OFPGMFC_INVALID_GROUP        = 1;  /* Group not added because Group
+                                          specified is invalid. */
+    OFPGMFC_WEIGHT_UNSUPPORTED   = 2;  /* Switch does not support unequal load
+                                          sharing with select groups. */
+    OFPGMFC_OUT_OF_GROUPS        = 3;  /* The group table is full. */
+    OFPGMFC_OUT_OF_BUCKETS       = 4;  /* The maximum number of action buckets
+                                          for a group has been exceeded. */
+    OFPGMFC_CHAINING_UNSUPPORTED = 5;  /* Switch does not support groups that
+                                          forward to groups. */
+    OFPGMFC_WATCH_UNSUPPORTED    = 6;  /* This group cannot watch the
+                                          watch_port or watch_group specified.
+                                        */
+    OFPGMFC_LOOP                 = 7;  /* Group entry would cause a loop. */
+    OFPGMFC_UNKNOWN_GROUP        = 8;  /* Group not modified because a group
+                                          MODIFY attempted to modify a
+                                          non-existent group. */
+    OFPGMFC_CHAINED_GROUP        = 9;  /* Group not deleted because another
+                                          group is forwarding to it. */
+    OFPGMFC_BAD_TYPE             = 10; /* Unsupported or unknown group type. */
+    OFPGMFC_BAD_COMMAND          = 11; /* Unsupported or unknown command. */
+    OFPGMFC_BAD_BUCKET           = 12; /* Error in bucket. */
+    OFPGMFC_BAD_WATCH            = 13; /* Error in watch port/group. */
+    OFPGMFC_EPERM                = 14; /* Permissions error. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_PORT_MOD_FAILED.  'data' contains
+ * at least the first 64 bytes of the failed request. */
+enum ofp_port_mod_failed_code {
+    OFPPMFC_BAD_PORT      = 0;   /* Specified port number does not exist. */
+    OFPPMFC_BAD_HW_ADDR   = 1;   /* Specified hardware address does not
+                                  * match the port number. */
+    OFPPMFC_BAD_CONFIG    = 2;   /* Specified config is invalid. */
+    OFPPMFC_BAD_ADVERTISE = 3;   /* Specified advertise is invalid. */
+    OFPPMFC_EPERM         = 4;   /* Permissions error. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_TABLE_MOD_FAILED.  'data' contains
+ * at least the first 64 bytes of the failed request. */
+enum ofp_table_mod_failed_code {
+    OFPTMFC_BAD_TABLE  = 0;      /* Specified table does not exist. */
+    OFPTMFC_BAD_CONFIG = 1;      /* Specified config is invalid. */
+    OFPTMFC_EPERM      = 2;      /* Permissions error. */
+};
+
+/* ofp_error msg 'code' values for OFPET_QUEUE_OP_FAILED. 'data' contains
+ * at least the first 64 bytes of the failed request */
+enum ofp_queue_op_failed_code {
+    OFPQOFC_BAD_PORT   = 0;     /* Invalid port (or port does not exist). */
+    OFPQOFC_BAD_QUEUE  = 1;     /* Queue does not exist. */
+    OFPQOFC_EPERM      = 2;     /* Permissions error. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_SWITCH_CONFIG_FAILED. 'data' contains
+ * at least the first 64 bytes of the failed request. */
+enum ofp_switch_config_failed_code {
+    OFPSCFC_BAD_FLAGS  = 0;      /* Specified flags is invalid. */
+    OFPSCFC_BAD_LEN    = 1;      /* Specified len is invalid. */
+    OFPSCFC_EPERM      = 2;      /* Permissions error. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_ROLE_REQUEST_FAILED. 'data' contains
+ * at least the first 64 bytes of the failed request. */
+enum ofp_role_request_failed_code {
+    OFPRRFC_STALE      = 0;      /* Stale Message: old generation_id. */
+    OFPRRFC_UNSUP      = 1;      /* Controller role change unsupported. */
+    OFPRRFC_BAD_ROLE   = 2;      /* Invalid role. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_METER_MOD_FAILED.  'data' contains
+ * at least the first 64 bytes of the failed request. */
+enum ofp_meter_mod_failed_code {
+    OFPMMFC_UNKNOWN       = 0;  /* Unspecified error. */
+    OFPMMFC_METER_EXISTS  = 1;  /* Meter not added because a Meter ADD
+                                 * attempted to replace an existing Meter. */
+    OFPMMFC_INVALID_METER = 2;  /* Meter not added because Meter specified
+                                 * is invalid,
+                                 * or invalid meter in meter action. */
+    OFPMMFC_UNKNOWN_METER = 3;  /* Meter not modified because a Meter MODIFY
+                                 * attempted to modify a non-existent Meter,
+                                 * or bad meter in meter action. */
+    OFPMMFC_BAD_COMMAND   = 4;  /* Unsupported or unknown command. */
+    OFPMMFC_BAD_FLAGS     = 5;  /* Flag configuration unsupported. */
+    OFPMMFC_BAD_RATE      = 6;  /* Rate unsupported. */
+    OFPMMFC_BAD_BURST     = 7;  /* Burst size unsupported. */
+    OFPMMFC_BAD_BAND      = 8;  /* Band unsupported. */
+    OFPMMFC_BAD_BAND_VALUE = 9; /* Band value unsupported. */
+    OFPMMFC_OUT_OF_METERS = 10; /* No more meters available. */
+    OFPMMFC_OUT_OF_BANDS  = 11; /* The maximum number of properties
+                                 * for a meter has been exceeded. */
+};
+
+/* ofp_error_msg 'code' values for OFPET_TABLE_FEATURES_FAILED. 'data' contains
+ * at least the first 64 bytes of the failed request. */
+enum ofp_table_features_failed_code {
+    OFPTFFC_BAD_TABLE    = 0;      /* Specified table does not exist. */
+    OFPTFFC_BAD_METADATA = 1;      /* Invalid metadata mask. */
+    OFPTFFC_BAD_TYPE     = 2;      /* Unknown property type. */
+    OFPTFFC_BAD_LEN      = 3;      /* Length problem in properties. */
+    OFPTFFC_BAD_ARGUMENT = 4;      /* Unsupported property value. */
+    OFPTFFC_EPERM        = 5;      /* Permissions error. */
+};
+
+/* OFPT_ERROR: Error message (datapath -> controller). */
+message ofp_error_msg {
+    //ofp_header header;
+    uint32 type = 1;
+    uint32 code = 2;
+    bytes data = 3;          /* Variable-length data.  Interpreted based
+                                 on the type and code.  No padding. */
+};
+
+/* OFPET_EXPERIMENTER: Error message (datapath -> controller). */
+message ofp_error_experimenter_msg {
+    //ofp_header header;
+
+    uint32 type = 1;           /* OFPET_EXPERIMENTER. */
+    uint32 exp_type = 2;       /* Experimenter defined. */
+    uint32 experimenter = 3;   /* Experimenter ID which takes the same form
+                                    as in struct ofp_experimenter_header. */
+    bytes data = 4;              /* Variable-length data.  Interpreted based
+                                    on the type and code.  No padding. */
+};
+
+enum ofp_multipart_type {
+    /* Description of this OpenFlow switch.
+     * The request body is empty.
+     * The reply body is struct ofp_desc. */
+    OFPMP_DESC = 0;
+
+    /* Individual flow statistics.
+     * The request body is struct ofp_flow_stats_request.
+     * The reply body is an array of struct ofp_flow_stats. */
+    OFPMP_FLOW = 1;
+
+    /* Aggregate flow statistics.
+     * The request body is struct ofp_aggregate_stats_request.
+     * The reply body is struct ofp_aggregate_stats_reply. */
+    OFPMP_AGGREGATE = 2;
+
+    /* Flow table statistics.
+     * The request body is empty.
+     * The reply body is an array of struct ofp_table_stats. */
+    OFPMP_TABLE = 3;
+
+    /* Port statistics.
+     * The request body is struct ofp_port_stats_request.
+     * The reply body is an array of struct ofp_port_stats. */
+    OFPMP_PORT_STATS = 4;
+
+    /* Queue statistics for a port
+     * The request body is struct ofp_queue_stats_request.
+     * The reply body is an array of struct ofp_queue_stats */
+    OFPMP_QUEUE = 5;
+
+    /* Group counter statistics.
+     * The request body is struct ofp_group_stats_request.
+     * The reply is an array of struct ofp_group_stats. */
+    OFPMP_GROUP = 6;
+
+    /* Group description.
+     * The request body is empty.
+     * The reply body is an array of struct ofp_group_desc. */
+    OFPMP_GROUP_DESC = 7;
+
+    /* Group features.
+     * The request body is empty.
+     * The reply body is struct ofp_group_features. */
+    OFPMP_GROUP_FEATURES = 8;
+
+    /* Meter statistics.
+     * The request body is struct ofp_meter_multipart_requests.
+     * The reply body is an array of struct ofp_meter_stats. */
+    OFPMP_METER = 9;
+
+    /* Meter configuration.
+     * The request body is struct ofp_meter_multipart_requests.
+     * The reply body is an array of struct ofp_meter_config. */
+    OFPMP_METER_CONFIG = 10;
+
+    /* Meter features.
+     * The request body is empty.
+     * The reply body is struct ofp_meter_features. */
+    OFPMP_METER_FEATURES = 11;
+
+    /* Table features.
+     * The request body is either empty or contains an array of
+     * struct ofp_table_features containing the controller's
+     * desired view of the switch. If the switch is unable to
+     * set the specified view an error is returned.
+     * The reply body is an array of struct ofp_table_features. */
+    OFPMP_TABLE_FEATURES = 12;
+
+    /* Port description.
+     * The request body is empty.
+     * The reply body is an array of struct ofp_port. */
+    OFPMP_PORT_DESC = 13;
+
+    /* Experimenter extension.
+     * The request and reply bodies begin with
+     * struct ofp_experimenter_multipart_header.
+     * The request and reply bodies are otherwise experimenter-defined. */
+    OFPMP_EXPERIMENTER = 0xffff;
+};
+
+/* Backward compatibility with 1.3.1 - avoid breaking the API. */
+//#define ofp_multipart_types ofp_multipart_type
+
+enum ofp_multipart_request_flags {
+    OFPMPF_REQ_INVALID = 0;
+    OFPMPF_REQ_MORE  = 1;  /* More requests to follow. */
+};
+
+message ofp_multipart_request {
+    //ofp_header header;
+    ofp_multipart_type type = 1; /* One of the OFPMP_* constants. */
+    uint32 flags = 2;            /* OFPMPF_REQ_* flags. */
+    bytes body = 3;              /* Body of the request. 0 or more bytes. */
+};
+
+enum ofp_multipart_reply_flags {
+    OFPMPF_REPLY_INVALID = 0;
+    OFPMPF_REPLY_MORE  = 1;  /* More replies to follow. */
+};
+
+message ofp_multipart_reply {
+    //ofp_header header;
+    ofp_multipart_type type = 1; /* One of the OFPMP_* constants. */
+    uint32 flags = 2;            /* OFPMPF_REPLY_* flags. */
+    bytes body = 3;              /* Body of the reply. 0 or more bytes. */
+};
+
+//#define DESC_STR_LEN   256
+//#define SERIAL_NUM_LEN 32
+/* Body of reply to OFPMP_DESC request.  Each entry is a NULL-terminated
+ * ASCII string. */
+message ofp_desc {
+    string mfr_desc = 1;       /* Manufacturer description. */
+    string hw_desc = 2;        /* Hardware description. */
+    string sw_desc = 3;        /* Software description. */
+    string serial_num = 4;     /* Serial number. */
+    string dp_desc = 5;        /* Human readable description of datapath. */
+};
+
+/* Body for ofp_multipart_request of type OFPMP_FLOW. */
+message ofp_flow_stats_request {
+    uint32 table_id = 1;       /* ID of table to read (from ofp_table_stats),
+                                    OFPTT_ALL for all tables. */
+    uint32 out_port = 2;       /* Require matching entries to include this
+                                    as an output port.  A value of OFPP_ANY
+                                    indicates no restriction. */
+    uint32 out_group = 3;      /* Require matching entries to include this
+                                    as an output group.  A value of OFPG_ANY
+                                    indicates no restriction. */
+    uint64 cookie = 4;         /* Require matching entries to contain this
+                                    cookie value */
+    uint64 cookie_mask = 5;    /* Mask used to restrict the cookie bits that
+                                    must match. A value of 0 indicates
+                                    no restriction. */
+    ofp_match match = 6;         /* Fields to match. Variable size. */
+};
+
+/* Body of reply to OFPMP_FLOW request. */
+message ofp_flow_stats {
+    uint64 id = 14;            /* Unique ID of flow within device. */
+    uint32 table_id = 1;       /* ID of table flow came from. */
+    uint32 duration_sec = 2;   /* Time flow has been alive in seconds. */
+    uint32 duration_nsec = 3;  /* Time flow has been alive in nanoseconds
+                                  beyond duration_sec. */
+    uint32 priority = 4;       /* Priority of the entry. */
+    uint32 idle_timeout = 5;   /* Number of seconds idle before expiration. */
+    uint32 hard_timeout = 6;   /* Number of seconds before expiration. */
+    uint32 flags = 7;          /* Bitmap of OFPFF_* flags. */
+    uint64 cookie = 8;         /* Opaque controller-issued identifier. */
+    uint64 packet_count = 9;   /* Number of packets in flow. */
+    uint64 byte_count = 10;    /* Number of bytes in flow. */
+    ofp_match match = 12;      /* Description of fields. Variable size. */
+    repeated ofp_instruction instructions = 13; /* Instruction set
+                                                   (0 or more) */
+};
+
+/* Body for ofp_multipart_request of type OFPMP_AGGREGATE. */
+message ofp_aggregate_stats_request {
+    uint32 table_id = 1;      /* ID of table to read (from ofp_table_stats)
+                                 OFPTT_ALL for all tables. */
+    uint32 out_port = 2;      /* Require matching entries to include this
+                                 as an output port.  A value of OFPP_ANY
+                                 indicates no restriction. */
+    uint32 out_group = 3;     /* Require matching entries to include this
+                                 as an output group.  A value of OFPG_ANY
+                                 indicates no restriction. */
+    uint64 cookie = 4;        /* Require matching entries to contain this
+                                 cookie value */
+    uint64 cookie_mask = 5;   /* Mask used to restrict the cookie bits that
+                                 must match. A value of 0 indicates
+                                 no restriction. */
+    ofp_match match = 6;      /* Fields to match. Variable size. */
+};
+
+/* Body of reply to OFPMP_AGGREGATE request. */
+message ofp_aggregate_stats_reply {
+    uint64 packet_count = 1;   /* Number of packets in flows. */
+    uint64 byte_count = 2;     /* Number of bytes in flows. */
+    uint32 flow_count = 3;     /* Number of flows. */
+};
+
+/* Table Feature property types.
+ * Low order bit cleared indicates a property for a regular Flow Entry.
+ * Low order bit set indicates a property for the Table-Miss Flow Entry.
+ */
+enum ofp_table_feature_prop_type {
+    OFPTFPT_INSTRUCTIONS           = 0;  /* Instructions property. */
+    OFPTFPT_INSTRUCTIONS_MISS      = 1;  /* Instructions for table-miss. */
+    OFPTFPT_NEXT_TABLES            = 2;  /* Next Table property. */
+    OFPTFPT_NEXT_TABLES_MISS       = 3;  /* Next Table for table-miss. */
+    OFPTFPT_WRITE_ACTIONS          = 4;  /* Write Actions property. */
+    OFPTFPT_WRITE_ACTIONS_MISS     = 5;  /* Write Actions for table-miss. */
+    OFPTFPT_APPLY_ACTIONS          = 6;  /* Apply Actions property. */
+    OFPTFPT_APPLY_ACTIONS_MISS     = 7;  /* Apply Actions for table-miss. */
+    OFPTFPT_MATCH                  = 8;  /* Match property. */
+    OFPTFPT_WILDCARDS              = 10; /* Wildcards property. */
+    OFPTFPT_WRITE_SETFIELD         = 12; /* Write Set-Field property. */
+    OFPTFPT_WRITE_SETFIELD_MISS    = 13; /* Write Set-Field for table-miss. */
+    OFPTFPT_APPLY_SETFIELD         = 14; /* Apply Set-Field property. */
+    OFPTFPT_APPLY_SETFIELD_MISS    = 15; /* Apply Set-Field for table-miss. */
+    OFPTFPT_EXPERIMENTER           = 0xFFFE; /* Experimenter property. */
+    OFPTFPT_EXPERIMENTER_MISS      = 0xFFFF; /* Experimenter for table-miss. */
+};
+
+/* Common header for all Table Feature Properties */
+message ofp_table_feature_property {
+    ofp_table_feature_prop_type type = 1;   /* One of OFPTFPT_*. */
+    oneof value {
+        ofp_table_feature_prop_instructions instructions = 2;
+        ofp_table_feature_prop_next_tables next_tables = 3;
+        ofp_table_feature_prop_actions actions = 4;
+        ofp_table_feature_prop_oxm oxm = 5;
+        ofp_table_feature_prop_experimenter experimenter = 6;
+    }
+};
+
+/* Instructions property */
+message ofp_table_feature_prop_instructions {
+    /* One of OFPTFPT_INSTRUCTIONS,
+       OFPTFPT_INSTRUCTIONS_MISS. */
+    repeated ofp_instruction instructions = 1;   /* List of instructions */
+};
+
+/* Next Tables property */
+message ofp_table_feature_prop_next_tables {
+    /* One of OFPTFPT_NEXT_TABLES,
+       OFPTFPT_NEXT_TABLES_MISS. */
+    repeated uint32 next_table_ids = 1;     /* List of table ids. */
+};
+
+/* Actions property */
+message ofp_table_feature_prop_actions {
+    /* One of OFPTFPT_WRITE_ACTIONS,
+       OFPTFPT_WRITE_ACTIONS_MISS,
+       OFPTFPT_APPLY_ACTIONS,
+       OFPTFPT_APPLY_ACTIONS_MISS. */
+    repeated ofp_action actions = 1; /* List of actions */
+};
+
+/* Match, Wildcard or Set-Field property */
+message ofp_table_feature_prop_oxm {
+    /* One of OFPTFPT_MATCH,
+       OFPTFPT_WILDCARDS,
+       OFPTFPT_WRITE_SETFIELD,
+       OFPTFPT_WRITE_SETFIELD_MISS,
+       OFPTFPT_APPLY_SETFIELD,
+       OFPTFPT_APPLY_SETFIELD_MISS. */
+    /* TODO is this a uint32??? */
+    repeated uint32 oxm_ids = 3;    /* Array of OXM headers */
+};
+
+/* Experimenter table feature property */
+message ofp_table_feature_prop_experimenter {
+    /* One of OFPTFPT_EXPERIMENTER,
+       OFPTFPT_EXPERIMENTER_MISS. */
+    uint32         experimenter = 2; /* Experimenter ID which takes the same
+                                        form as in struct
+                                        ofp_experimenter_header. */
+    uint32         exp_type = 3;      /* Experimenter defined. */
+    repeated uint32 experimenter_data = 4;
+};
+
+/* Body for ofp_multipart_request of type OFPMP_TABLE_FEATURES./
+ * Body of reply to OFPMP_TABLE_FEATURES request. */
+message ofp_table_features {
+    uint32 table_id = 1;       /* Identifier of table.  Lower numbered tables
+                                are consulted first. */
+    string name = 2;
+    uint64 metadata_match = 3; /* Bits of metadata table can match. */
+    uint64 metadata_write = 4; /* Bits of metadata table can write. */
+    uint32 config = 5;         /* Bitmap of OFPTC_* values */
+    uint32 max_entries = 6;    /* Max number of entries supported. */
+
+    /* Table Feature Property list */
+    repeated ofp_table_feature_property properties = 7;
+};
+
+/* Body of reply to OFPMP_TABLE request. */
+message ofp_table_stats {
+    uint32 table_id = 1;      /* Identifier of table.  Lower numbered tables
+                                 are consulted first. */
+    uint32 active_count = 2;  /* Number of active entries. */
+    uint64 lookup_count = 3;  /* Number of packets looked up in table. */
+    uint64 matched_count = 4; /* Number of packets that hit table. */
+};
+
+/* Body for ofp_multipart_request of type OFPMP_PORT. */
+message ofp_port_stats_request {
+    uint32 port_no = 1;       /* OFPMP_PORT message must request statistics
+                               * either for a single port (specified in
+                               * port_no) or for all ports (if port_no ==
+                               * OFPP_ANY). */
+};
+
+/* Body of reply to OFPMP_PORT request. If a counter is unsupported, set
+ * the field to all ones. */
+message ofp_port_stats {
+    uint32 port_no = 1;
+    uint64 rx_packets = 2;   /* Number of received packets. */
+    uint64 tx_packets = 3;   /* Number of transmitted packets. */
+    uint64 rx_bytes = 4;     /* Number of received bytes. */
+    uint64 tx_bytes = 5;     /* Number of transmitted bytes. */
+    uint64 rx_dropped = 6;   /* Number of packets dropped by RX. */
+    uint64 tx_dropped = 7;   /* Number of packets dropped by TX. */
+    uint64 rx_errors = 8;    /* Number of receive errors.  This is a super-set
+                                of more specific receive errors and should be
+                                greater than or equal to the sum of all
+                                rx_*_err values. */
+    uint64 tx_errors = 9;    /* Number of transmit errors.  This is a super-set
+                                of more specific transmit errors and should be
+                                greater than or equal to the sum of all
+                                tx_*_err values (none currently defined.) */
+    uint64 rx_frame_err = 10;  /* Number of frame alignment errors. */
+    uint64 rx_over_err = 11;   /* Number of packets with RX overrun. */
+    uint64 rx_crc_err = 12;    /* Number of CRC errors. */
+    uint64 collisions = 13;    /* Number of collisions. */
+    uint32 duration_sec = 14;  /* Time port has been alive in seconds. */
+    uint32 duration_nsec = 15; /* Time port has been alive in nanoseconds
+                                  beyond duration_sec. */
+};
+
+/* Body of OFPMP_GROUP request. */
+message ofp_group_stats_request {
+    uint32 group_id = 1;      /* All groups if OFPG_ALL. */
+};
+
+/* Used in group stats replies. */
+message ofp_bucket_counter {
+    uint64 packet_count = 1;  /* Number of packets processed by bucket. */
+    uint64 byte_count = 2;    /* Number of bytes processed by bucket. */
+};
+
+/* Body of reply to OFPMP_GROUP request. */
+message ofp_group_stats {
+    uint32 group_id = 1;      /* Group identifier. */
+    uint32 ref_count = 2;     /* Number of flows or groups that directly
+                                 forward to this group. */
+    uint64 packet_count = 3;  /* Number of packets processed by group. */
+    uint64 byte_count = 4;    /* Number of bytes processed by group. */
+    uint32 duration_sec = 5;  /* Time group has been alive in seconds. */
+    uint32 duration_nsec = 6; /* Time group has been alive in nanoseconds
+                                 beyond duration_sec. */
+    repeated ofp_bucket_counter bucket_stats = 7; /* One counter set per
+                                                     bucket. */
+};
+
+/* Body of reply to OFPMP_GROUP_DESC request. */
+message ofp_group_desc {
+    ofp_group_type type = 1;       /* One of OFPGT_*. */
+    uint32 group_id = 2;           /* Group identifier. */
+    repeated ofp_bucket buckets = 3;   /* List of buckets - 0 or more. */
+};
+
+message ofp_group_entry {
+    ofp_group_desc desc = 1;
+    ofp_group_stats stats = 2;
+};
+
+/* Backward compatibility with 1.3.1 - avoid breaking the API. */
+//#define ofp_group_desc_stats ofp_group_desc
+
+/* Group configuration flags */
+enum ofp_group_capabilities {
+    OFPGFC_INVALID         = 0;
+    OFPGFC_SELECT_WEIGHT   = 1;  /* Support weight for select groups */
+    OFPGFC_SELECT_LIVENESS = 2;  /* Support liveness for select groups */
+    OFPGFC_CHAINING        = 4;  /* Support chaining groups */
+    OFPGFC_CHAINING_CHECKS = 8;  /* Check chaining for loops and delete */
+};
+
+/* Body of reply to OFPMP_GROUP_FEATURES request. Group features. */
+message ofp_group_features {
+    uint32  types = 1;         /* Bitmap of (1 << OFPGT_*) values supported. */
+    uint32  capabilities = 2;  /* Bitmap of OFPGFC_* capability supported. */
+    repeated uint32 max_groups = 3; /* Maximum number of groups for each type.
+                                     */
+    repeated uint32 actions = 4;    /* Bitmaps of (1 << OFPAT_*) values
+                                       supported. */
+};
+
+/* Body of OFPMP_METER and OFPMP_METER_CONFIG requests. */
+message ofp_meter_multipart_request {
+    uint32 meter_id = 1;      /* Meter instance, or OFPM_ALL. */
+};
+
+/* Statistics for each meter band */
+message ofp_meter_band_stats {
+    uint64        packet_band_count = 1;  /* Number of packets in band. */
+    uint64        byte_band_count = 2;    /* Number of bytes in band. */
+};
+
+/* Body of reply to OFPMP_METER request. Meter statistics. */
+message ofp_meter_stats {
+    uint32        meter_id = 1;        /* Meter instance. */
+    uint32        flow_count = 2;      /* Number of flows bound to meter. */
+    uint64        packet_in_count = 3; /* Number of packets in input. */
+    uint64        byte_in_count = 4;   /* Number of bytes in input. */
+    uint32        duration_sec = 5; /* Time meter has been alive in seconds. */
+    uint32        duration_nsec = 6;/* Time meter has been alive in nanoseconds
+                                       beyond duration_sec. */
+    repeated ofp_meter_band_stats band_stats = 7; /* The band_stats length is
+                                         inferred from the length field. */
+};
+
+/* Body of reply to OFPMP_METER_CONFIG request. Meter configuration. */
+message ofp_meter_config {
+    uint32        flags = 1;           /* All OFPMF_* that apply. */
+    uint32        meter_id = 2;        /* Meter instance. */
+    repeated ofp_meter_band_header bands = 3; /* The bands length is
+                                             inferred from the length field. */
+};
+
+/* Body of reply to OFPMP_METER_FEATURES request. Meter features. */
+message ofp_meter_features {
+    uint32    max_meter = 1;    /* Maximum number of meters. */
+    uint32    band_types = 2;   /* Bitmaps of (1 << OFPMBT_*) values supported.
+                                 */
+    uint32    capabilities = 3; /* Bitmaps of "ofp_meter_flags". */
+    uint32    max_bands = 4;    /* Maximum bands per meters */
+    uint32    max_color = 5;    /* Maximum color value */
+};
+
+/* Body for ofp_multipart_request/reply of type OFPMP_EXPERIMENTER. */
+message ofp_experimenter_multipart_header {
+    uint32 experimenter = 1;   /* Experimenter ID which takes the same form
+                                  as in struct ofp_experimenter_header. */
+    uint32 exp_type = 2;       /* Experimenter defined. */
+    bytes data = 3; /* Experimenter-defined arbitrary additional data. */
+};
+
+/* Experimenter extension. */
+message ofp_experimenter_header {
+    //ofp_header header;  /* Type OFPT_EXPERIMENTER. */
+    uint32 experimenter = 1;     /* Experimenter ID:
+                                 * - MSB 0: low-order bytes are IEEE OUI.
+                                 * - MSB != 0: defined by ONF. */
+    uint32 exp_type = 2;         /* Experimenter defined. */
+    bytes data = 3; /* Experimenter-defined arbitrary additional data. */
+};
+
+/* All ones is used to indicate all queues in a port (for stats retrieval). */
+//#define OFPQ_ALL      0xffffffff
+
+/* Min rate > 1000 means not configured. */
+//#define OFPQ_MIN_RATE_UNCFG      0xffff
+
+/* Max rate > 1000 means not configured. */
+//#define OFPQ_MAX_RATE_UNCFG      0xffff
+
+enum ofp_queue_properties {
+    OFPQT_INVALID       = 0;
+    OFPQT_MIN_RATE      = 1;      /* Minimum datarate guaranteed. */
+    OFPQT_MAX_RATE      = 2;      /* Maximum datarate. */
+    OFPQT_EXPERIMENTER  = 0xffff; /* Experimenter defined property. */
+};
+
+/* Common description for a queue. */
+message ofp_queue_prop_header {
+    uint32 property = 1;   /* One of OFPQT_. */
+    uint32 len = 2;        /* Length of property, including this header. */
+};
+
+/* Min-Rate queue property description. */
+message ofp_queue_prop_min_rate {
+    ofp_queue_prop_header prop_header = 1;/* prop: OFPQT_MIN, len: 16. */
+    uint32 rate = 2;       /* In 1/10 of a percent = 0;>1000 -> disabled. */
+};
+
+/* Max-Rate queue property description. */
+message ofp_queue_prop_max_rate {
+    ofp_queue_prop_header prop_header = 1;/* prop: OFPQT_MAX, len: 16. */
+    uint32 rate = 2;       /* In 1/10 of a percent = 0;>1000 -> disabled. */
+};
+
+/* Experimenter queue property description. */
+message ofp_queue_prop_experimenter {
+    ofp_queue_prop_header prop_header = 1;/* prop: OFPQT_EXPERIMENTER */
+    uint32 experimenter = 2;         /* Experimenter ID which takes the same
+                                          form as in struct
+                                          ofp_experimenter_header. */
+    bytes data = 3;                    /* Experimenter defined data. */
+};
+
+/* Full description for a queue. */
+message ofp_packet_queue {
+    uint32 queue_id = 1;    /* id for the specific queue. */
+    uint32 port = 2;        /* Port this queue is attached to. */
+    repeated ofp_queue_prop_header properties = 4; /* List of properties. */
+};
+
+/* Query for port queue configuration. */
+message ofp_queue_get_config_request {
+    //ofp_header header;
+    uint32 port = 1;        /* Port to be queried. Should refer
+                              to a valid physical port (i.e. <= OFPP_MAX),
+                              or OFPP_ANY to request all configured
+                              queues.*/
+};
+
+/* Queue configuration for a given port. */
+message ofp_queue_get_config_reply {
+    //ofp_header header;
+    uint32 port = 1;
+    repeated ofp_packet_queue queues = 2; /* List of configured queues. */
+};
+
+/* OFPAT_SET_QUEUE action struct: send packets to given queue on port. */
+message ofp_action_set_queue {
+    uint32 type = 1;           /* OFPAT_SET_QUEUE. */
+    uint32 queue_id = 3;       /* Queue id for the packets. */
+};
+
+message ofp_queue_stats_request {
+    uint32 port_no = 1;       /* All ports if OFPP_ANY. */
+    uint32 queue_id = 2;      /* All queues if OFPQ_ALL. */
+};
+
+message ofp_queue_stats {
+    uint32 port_no = 1;
+    uint32 queue_id = 2;      /* Queue i.d */
+    uint64 tx_bytes = 3;      /* Number of transmitted bytes. */
+    uint64 tx_packets = 4;    /* Number of transmitted packets. */
+    uint64 tx_errors = 5;     /* Number of packets dropped due to overrun. */
+    uint32 duration_sec = 6;  /* Time queue has been alive in seconds. */
+    uint32 duration_nsec = 7; /* Time queue has been alive in nanoseconds
+                                 beyond duration_sec. */
+};
+
+/* Configures the "role" of the sending controller.  The default role is:
+ *
+ *    - Equal (OFPCR_ROLE_EQUAL), which allows the controller access to all
+ *      OpenFlow features. All controllers have equal responsibility.
+ *
+ * The other possible roles are a related pair:
+ *
+ *    - Master (OFPCR_ROLE_MASTER) is equivalent to Equal, except that there
+ *      may be at most one Master controller at a time: when a controller
+ *      configures itself as Master, any existing Master is demoted to the
+ *      Slave role.
+ *
+ *    - Slave (OFPCR_ROLE_SLAVE) allows the controller read-only access to
+ *      OpenFlow features.  In particular attempts to modify the flow table
+ *      will be rejected with an OFPBRC_EPERM error.
+ *
+ *      Slave controllers do not receive OFPT_PACKET_IN or OFPT_FLOW_REMOVED
+ *      messages, but they do receive OFPT_PORT_STATUS messages.
+ */
+
+/* Controller roles. */
+enum ofp_controller_role {
+    OFPCR_ROLE_NOCHANGE = 0;    /* Don't change current role. */
+    OFPCR_ROLE_EQUAL    = 1;    /* Default role, full access. */
+    OFPCR_ROLE_MASTER   = 2;    /* Full access, at most one master. */
+    OFPCR_ROLE_SLAVE    = 3;    /* Read-only access. */
+};
+
+/* Role request and reply message. */
+message ofp_role_request {
+    //ofp_header header;        /* Type OFPT_ROLE_REQUEST/OFPT_ROLE_REPLY. */
+    ofp_controller_role role = 1; /* One of OFPCR_ROLE_*. */
+    uint64 generation_id = 2;     /* Master Election Generation Id */
+};
+
+/* Asynchronous message configuration. */
+message ofp_async_config {
+    //ofp_header header;    /* OFPT_GET_ASYNC_REPLY or OFPT_SET_ASYNC. */
+    repeated uint32 packet_in_mask = 1;   /* Bitmasks of OFPR_* values. */
+    repeated uint32 port_status_mask = 2; /* Bitmasks of OFPPR_* values. */
+    repeated uint32 flow_removed_mask = 3;/* Bitmasks of OFPRR_* values. */
+};
+
+
+/* ADDITIONAL VOLTHA SPECIFIC MESSAGE TYPES, AIDING RPC CALLS */
+
+message FlowTableUpdate {
+    string id = 1;  // Device.id or LogicalDevice.id
+    ofp_flow_mod flow_mod = 2;
+}
+
+message FlowGroupTableUpdate {
+    string id = 1;  // Device.id or LogicalDevice.id
+    ofp_group_mod group_mod = 2;
+}
+
+message Flows {
+    repeated ofp_flow_stats items = 1;
+}
+
+message FlowGroups {
+    repeated ofp_group_entry items = 1;
+}
+
+message PacketIn {
+    string id = 1;  // LogicalDevice.id
+    ofp_packet_in packet_in = 2;
+}
+
+message PacketOut {
+    string id = 1;  // LogicalDevice.id
+    ofp_packet_out packet_out = 2;
+}
diff --git a/experiments/netconf/proto2yang/proto2yang.py b/experiments/netconf/proto2yang/proto2yang.py
index 8d9a40b..ae1999e 100755
--- a/experiments/netconf/proto2yang/proto2yang.py
+++ b/experiments/netconf/proto2yang/proto2yang.py
@@ -43,9 +43,27 @@
 
 template_yang = Template("""
 module ietf-{{ module.name }} {
-    yang-version 1.1;
-    namespace "urn:ietf:params:xml:ns:yang:ietf-{{ module.name }}";
-    prefix "voltha";
+
+    {% macro set_module_prefix(type) %}
+        {% for t in module.data_types %}
+            {% if t.type == type %}
+                {% if t.module != module.name %} {{ t.module }}:{{ type }};
+                {% else %} {{ type }};
+                {% endif %}
+                {% set found=True %}
+            {% endif %}
+        {% if loop.last %}
+            {% if not found %} {{ type }}; {% endif %}
+        {% endif %}
+        {% endfor %}
+    {% endmacro %}
+
+    namespace "urn:opencord:params:xml:ns:voltha:ietf-{{ module.name }}";
+    prefix {{ module.name }};
+
+    {% for imp in module.imports %}
+    import ietf-{{ imp.name }} { prefix {{ imp.name }} ; }
+    {% endfor %}
 
     organization "CORD";
     contact
@@ -74,7 +92,7 @@
     {% endfor %}
 
     {% for message in module.messages recursive %}
-    {% if message.name in module.referenced_messages %}
+    {% if message.name in module.referred_messages %}
     grouping {{ message.name }} {
     {% else %}
     container {{ message.name }} {
@@ -84,17 +102,21 @@
         {% for field in message.fields %}
         {% if field.type_ref %}
         {% for dict_item in module.referred_messages_with_keys %}
-                {% if dict_item.name == field.type %}
+            {% if dict_item.name == field.type %}
+                {% if not field.repeated %}
+        container {{ field.name }} {
+                {% else %}
         list {{ field.name }} {
             key "{{ dict_item.key }}";
             {% if not field.repeated %}
             max-elements 1;
             {% endif %}
-            uses {{ field.type }};
+            {% endif %}
+            uses {{ set_module_prefix(field.type) }}
             description
                 "{{ field.description }}";
         }
-                {% endif %}
+            {% endif %}
         {% endfor %}
         {% elif field.repeated %}
         list {{ field.name }} {
@@ -105,7 +127,7 @@
                    fraction-digits 5;
                 }
                 {% else %}
-                type {{ field.type }};
+                type {{ set_module_prefix(field.type) }}
                 {% endif %}
                 description
                     "{{ field.description }}";
@@ -120,7 +142,7 @@
                fraction-digits 5;
             }
             {% else %}
-            type {{ field.type }};
+            type {{ set_module_prefix(field.type) }}
             {% endif %}
             description
                 "{{ field.description }}";
@@ -159,10 +181,10 @@
         {% if method.input %}
         input {
             {% if method.input_ref %}
-            uses {{ method.input }};
+            uses {{ set_module_prefix(method.input) }}
             {% else %}
             leaf {{ method.input }} {
-                type {{ method.input }};
+                type {{ set_module_prefix(method.input) }}
             }
             {% endif %}
         }
@@ -170,10 +192,10 @@
         {% if method.output %}
         output {
             {% if method.output_ref %}
-            uses {{ method.output }};
+            uses {{ set_module_prefix(method.output) }}
             {% else %}
             leaf {{ method.output }} {
-                type {{ method.output }};
+                type {{ set_module_prefix(method.output) }}
             }
             {% endif %}
         }
@@ -186,6 +208,19 @@
 }
 """, trim_blocks=True, lstrip_blocks=True)
 
+# def traverse_dependencies(descriptor):
+#     dependencies = []
+#     proto_imports = descriptor.get('dependency', [])
+#     for proto_import in proto_imports:
+#         # If the import file has a directory path to it remove it as it is not
+#         # allowed in Yang.  The proto extension should be removed as well
+#         dependencies.append (
+#             {
+#             'name' : proto_import.split('/')[-1][:-len('.proto')]
+#             }
+#         )
+#     return dependencies
+
 
 def traverse_messages(message_types, prefix, referenced_messages):
     messages = []
@@ -230,6 +265,9 @@
         _type = get_yang_type(field)
         if not yang_base_type:
             referenced_messages.append(_type)
+        # add to referred messages also if it is an enumeration type
+        if is_enumeration(field['type']):
+            referenced_messages.append(_type)
 
         fields.append(
             {
@@ -326,6 +364,7 @@
     name = rchop(descriptor.get('name', ''), '.proto')
     package = descriptor.get('package', '')
     description = descriptor.get('_description', '')
+    # imports=traverse_dependencies(descriptor)
     messages = traverse_messages(descriptor.get('message_type', []),
                                  package, referenced_messages)
     enums = traverse_enums(descriptor.get('enum_type', []), package)
@@ -333,26 +372,33 @@
                                  referenced_messages)
     # extensions = _traverse_extensions(descriptors)
     # options = _traverse_options(descriptors)
-    set_messages_keys(messages)
-    unique_referred_messages_with_keys = []
-    for message_name in list(set(referenced_messages)):
-        unique_referred_messages_with_keys.append(
-            {
-                'name': message_name,
-                'key': get_message_key(message_name, messages)
-            }
-        )
+    # set_messages_keys(messages)
+    # unique_referred_messages_with_keys = []
+    # for message_name in list(set(referenced_messages)):
+    #     unique_referred_messages_with_keys.append(
+    #         {
+    #             'name': message_name,
+    #             'key': get_message_key(message_name, messages)
+    #         }
+    #     )
+
+    # Get a list of type definitions (messages, enums) defined in this
+    # descriptor
+    defined_types = [m['name'].split('/')[-1] for m in messages] + \
+                    [e['name'].split('/')[-1]  for e in enums]
 
     data = {
-        'name': name,
+        'name': name.split('/')[-1],
         'package': package,
         'description': description,
+        # 'imports' : imports,
         'messages': messages,
         'enums': enums,
         'services': services,
+        'defined_types' : defined_types,
         'referenced_messages': list(set(referenced_messages)),
         # TODO:  simplify for easier jinja2 template use
-        'referred_messages_with_keys': unique_referred_messages_with_keys,
+        # 'referred_messages_with_keys': unique_referred_messages_with_keys,
         # 'extensions': extensions,
         # 'options': options
     }
@@ -361,22 +407,35 @@
 
 def set_messages_keys(messages):
     for message in messages:
-        message['key'] = _get_message_key(message)
+        message['key'] = _get_message_key(message, messages)
         if message['messages']:
             set_messages_keys(message['messages'])
 
-
-def _get_message_key(message):
+def _get_message_key(message, messages):
     # assume key is first yang base type field
     for field in message['fields']:
         if not field['type_ref']:
             return field['name']
+        else:
+            # if the field name is a message then loop for the key in that
+            # message
+            ref_message = _get_message(field['type'], messages)
+            if ref_message:
+                return _get_message_key(ref_message, messages)
+
     # no key yet - search nested messaged
-    if message['messages']:
-        return get_message_key(message['messages'])
+    for m in message['messages']:
+        key = _get_message_key(m, messages)
+        if key is not None:
+            return key
     else:
         return None
 
+def _get_message(name, messages):
+    for m in messages:
+        if m['name'] == name:
+            return m
+    return None
 
 def get_message_key(message_name, messages):
     for message in messages:
@@ -387,30 +446,76 @@
     return None
 
 
+def update_module_imports(module):
+    used_imports = set()
+    for ref_msg in module['referenced_messages']:
+        for type_dict in module['data_types']:
+            if ref_msg == type_dict['type']:
+                if module['name'] != type_dict['module']:
+                    used_imports.add(type_dict['module'])
+                break
+    module['imports'] = [{'name' : i} for i in used_imports]
+
+
 def generate_code(request, response):
     assert isinstance(request, plugin.CodeGeneratorRequest)
 
     parser = DescriptorParser()
 
-    # idx = 1
+    # First process the proto file with the imports
+    all_defined_types = []
+    all_proto_data = []
+    all_referred_messages = []
+    all_messages = []
     for proto_file in request.proto_file:
         native_data = parser.parse_file_descriptor(proto_file,
                                                    type_tag_name='_type',
                                                    fold_comments=True)
 
-        # print native_data
+        # Consolidate the defined types across imports
         yang_data = traverse_desc(native_data)
+        for type in yang_data['defined_types']:
+            all_defined_types.append(
+                {
+                    'type' : type,
+                    'module' : yang_data['name']
+                }
+            )
 
+        all_proto_data.append(
+            {
+                'file_name': '{}-{}'.format('ietf', proto_file.name.split(
+                    '/')[-1].replace('.proto','.yang')),
+                'module': yang_data
+            }
+        )
+
+        # Consolidate referred messages across imports
+        all_referred_messages = all_referred_messages + yang_data['referenced_messages']
+
+        # consolidate all messages
+        all_messages = all_messages + yang_data['messages']
+
+    # Set the message keys - required for List definitions (repeated label)
+    set_messages_keys(all_messages)
+    unique_referred_messages_with_keys = []
+    for m in all_messages:
+        unique_referred_messages_with_keys.append(
+                {
+                    'name': m['name'],
+                    'key': m['key']
+                }
+            )
+
+    # Create the files
+    for proto_data in all_proto_data:
         f = response.file.add()
-        # TODO: We should have a separate file for each output. There is an
-        # issue reusing the same filename with an incremental suffix.  Using
-        # a different file name works but not the actual proto file name
-        f.name = '{}-{}'.format('ietf', proto_file.name.replace('.proto',
-                                                                '.yang'))
-        # f.name = '{}_{}{}'.format(_rchop(proto_file.name, '.proto'), idx,
-        #                            '.yang')
-        # idx += 1
-        f.content = template_yang.render(module=yang_data)
+        f.name = proto_data['file_name']
+        proto_data['module']['data_types'] = all_defined_types
+        proto_data['module']['referred_messages'] = all_referred_messages
+        proto_data['module']['referred_messages_with_keys'] = unique_referred_messages_with_keys
+        update_module_imports(proto_data['module'])
+        f.content = template_yang.render(module=proto_data['module'])
 
 
 def get_yang_type(field):
@@ -426,6 +531,11 @@
     else:
         return type
 
+def is_enumeration(type):
+    if type in YANG_TYPE_MAP.keys():
+        _type, _ = YANG_TYPE_MAP[type]
+        return _type in ['enumeration']
+    return False
 
 def is_base_type(type):
     # check numeric value of the type first
@@ -435,7 +545,8 @@
     else:
         # proto name of the type
         result = [_format for (_, _format) in YANG_TYPE_MAP.values() if
-                  _format == type and _format not in ['message', 'group']]
+                  _format == type and _format not in ['message',
+                                                      'group']]
         return len(result) > 0
 
 
diff --git a/experiments/netconf/proto2yang/schema.proto b/experiments/netconf/proto2yang/schema.proto
new file mode 100644
index 0000000..e75f696
--- /dev/null
+++ b/experiments/netconf/proto2yang/schema.proto
@@ -0,0 +1,36 @@
+syntax = "proto3";
+
+package schema;
+
+import "google/api/annotations.proto";
+import "google/protobuf/empty.proto";
+
+// Contains the name and content of a *.proto file
+message ProtoFile {
+    string file_name = 1;  // name of proto file
+    string proto = 2;  // content of proto file
+    bytes descriptor = 3;  // compiled descriptor for proto (zlib compressed)
+}
+
+// Proto files and compiled descriptors for this interface
+message Schemas {
+
+    // Proto files
+    repeated ProtoFile protos = 1;
+
+    // Proto file name from which swagger.json shall be generated
+    string swagger_from = 2;
+
+}
+
+// Schema services
+service SchemaService {
+
+    // Return active grpc schemas
+    rpc GetSchema(google.protobuf.Empty) returns (Schemas) {
+        option (google.api.http) = {
+            get: "/schema"
+        };
+    }
+
+}
diff --git a/experiments/netconf/proto2yang/test.proto b/experiments/netconf/proto2yang/test.proto
new file mode 100644
index 0000000..802ae0d
--- /dev/null
+++ b/experiments/netconf/proto2yang/test.proto
@@ -0,0 +1,19 @@
+// See README.txt for information and build instructions.
+
+syntax = "proto3";
+
+package voltha;
+
+import public "common.proto";
+
+option java_package = "com.example.tutorial";
+option java_outer_classname = "AddressBookProtos";
+option csharp_namespace = "Google.Protobuf.Examples.AddressBook";
+
+message Person {
+  string name = 1;
+  int32 id = 2;        // Unique ID number for this person.
+  string email = 3;
+
+  LogLevel.LogLevel log_level = 4;
+}
diff --git a/experiments/netconf/proto2yang/voltha.proto b/experiments/netconf/proto2yang/voltha.proto
new file mode 100644
index 0000000..b76d903
--- /dev/null
+++ b/experiments/netconf/proto2yang/voltha.proto
@@ -0,0 +1,421 @@
+/*
+ * Top-level Voltha API definition
+ *
+ * For details, see individual definition files.
+ */
+
+syntax = "proto3";
+
+package voltha;
+
+import "google/protobuf/empty.proto";
+import "google/api/annotations.proto";
+
+import public "meta.proto";
+import public "common.proto";
+import public "health.proto";
+import public "logical_device.proto";
+import public "device.proto";
+import public "adapter.proto";
+import public "openflow_13.proto";
+
+option java_package = "org.opencord.voltha";
+option java_outer_classname = "VolthaProtos";
+option csharp_namespace = "Opencord.Voltha.Voltha";
+
+message DeviceGroup {
+
+    string id = 1 [(access) = READ_ONLY];
+
+    repeated LogicalDevice logical_devices = 2 [(child_node) = {key: "id"}];
+
+    repeated Device devices = 3 [(child_node) = {key: "id"}];
+}
+
+message DeviceGroups {
+    repeated DeviceGroup items = 1;
+}
+
+// Top-level (root) node for a Voltha Instance
+message VolthaInstance {
+
+    string instance_id = 1  [(access) = READ_ONLY];
+
+    string version = 2 [(access) = READ_ONLY];
+
+    LogLevel log_level = 3;
+
+    HealthStatus health = 10 [(child_node) = {}];
+
+    repeated Adapter adapters = 11 [(child_node) = {key: "id" }];
+
+    repeated LogicalDevice logical_devices = 12 [(child_node) = {key: "id"}];
+
+    repeated Device devices = 13 [(child_node) = {key: "id"}];
+
+    repeated DeviceType device_types = 14 [(child_node) = {key: "id"}];
+
+    repeated DeviceGroup device_groups = 15 [(child_node) = {key: "id"}];
+}
+
+message VolthaInstances {
+    repeated string items = 1;
+}
+
+// Voltha representing the entire Voltha cluster
+message Voltha {
+
+    string version = 1 [(access) = READ_ONLY];
+
+    LogLevel log_level = 2;
+
+    repeated VolthaInstance instances = 3 [(child_node) = {key: "instance_id"}];
+
+    repeated Adapter adapters = 11 [(child_node) = {key: "id"}];
+
+    repeated LogicalDevice logical_devices = 12 [(child_node) = {key: "id"}];
+
+    repeated Device devices = 13 [(child_node) = {key: "id"}];
+
+    repeated DeviceGroup device_groups = 15 [(child_node) = {key: "id"}];
+
+}
+
+
+/*
+ * Cluster-wide Voltha APIs
+ *
+ * These APIs are potentially dispatched to the leader of the Voltha cluster,
+ * to a specific Voltha instance which owns the given device or logical device.
+ *
+ */
+service VolthaGlobalService {
+
+    // Get high level information on the Voltha cluster
+    rpc GetVoltha(google.protobuf.Empty) returns(Voltha) {
+        option (google.api.http) = {
+            get: "/api/v1"
+        };
+    }
+
+    // List all Voltha cluster instances
+    rpc ListVolthaInstances(google.protobuf.Empty) returns(VolthaInstances) {
+        option (google.api.http) = {
+            get: "/api/v1/instances"
+        };
+    }
+
+    // Get details on a Voltha cluster instance
+    rpc GetVolthaInstance(ID) returns(VolthaInstance) {
+        option (google.api.http) = {
+            get: "/api/v1/instances/{id}"
+        };
+    }
+
+    // List all logical devices managed by the Voltha cluster
+    rpc ListLogicalDevices(google.protobuf.Empty) returns(LogicalDevices) {
+        option (google.api.http) = {
+            get: "/api/v1/logical_devices"
+        };
+    }
+
+    // Get additional information on a given logical device
+    rpc GetLogicalDevice(ID) returns(LogicalDevice) {
+        option (google.api.http) = {
+            get: "/api/v1/logical_devices/{id}"
+        };
+    }
+
+    // List ports of a logical device
+    rpc ListLogicalDevicePorts(ID) returns(LogicalPorts) {
+        option (google.api.http) = {
+            get: "/api/v1/logical_devices/{id}/ports"
+        };
+    }
+
+    // List all flows of a logical device
+    rpc ListLogicalDeviceFlows(ID) returns(openflow_13.Flows) {
+        option (google.api.http) = {
+            get: "/api/v1/logical_devices/{id}/flows"
+        };
+    }
+
+    // Update flow table for logical device
+    rpc UpdateLogicalDeviceFlowTable(openflow_13.FlowTableUpdate)
+            returns(google.protobuf.Empty) {
+        option (google.api.http) = {
+            post: "/api/v1/logical_devices/{id}/flows"
+            body: "*"
+        };
+    }
+
+    // List all flow groups of a logical device
+    rpc ListLogicalDeviceFlowGroups(ID) returns(openflow_13.FlowGroups) {
+        option (google.api.http) = {
+            get: "/api/v1/logical_devices/{id}/flow_groups"
+        };
+    }
+
+    // Update group table for device
+    rpc UpdateLogicalDeviceFlowGroupTable(openflow_13.FlowGroupTableUpdate)
+            returns(google.protobuf.Empty) {
+        option (google.api.http) = {
+            post: "/api/v1/logical_devices/{id}/flow_groups"
+            body: "*"
+        };
+    }
+
+    // List all physical devices controlled by the Voltha cluster
+    rpc ListDevices(google.protobuf.Empty) returns(Devices) {
+        option (google.api.http) = {
+            get: "/api/v1/devices"
+        };
+    }
+
+    // Get more information on a given physical device
+    rpc GetDevice(ID) returns(Device) {
+        option (google.api.http) = {
+            get: "/api/v1/devices/{id}"
+        };
+    }
+
+    // Pre-provision a new physical device
+    rpc CreateDevice(Device) returns(Device) {
+        option (google.api.http) = {
+            post: "/api/v1/devices"
+            body: "*"
+        };
+    }
+
+    // Activate a pre-provisioned device
+    rpc ActivateDevice(ID) returns(google.protobuf.Empty) {
+        option (google.api.http) = {
+            post: "/api/v1/devices/{id}/activate"
+        };
+    }
+
+    // List ports of a device
+    rpc ListDevicePorts(ID) returns(Ports) {
+        option (google.api.http) = {
+            get: "/api/v1/devices/{id}/ports"
+        };
+    }
+
+    // List all flows of a device
+    rpc ListDeviceFlows(ID) returns(openflow_13.Flows) {
+        option (google.api.http) = {
+            get: "/api/v1/devices/{id}/flows"
+        };
+    }
+
+    // List all flow groups of a device
+    rpc ListDeviceFlowGroups(ID) returns(openflow_13.FlowGroups) {
+        option (google.api.http) = {
+            get: "/api/v1/devices/{id}/flow_groups"
+        };
+    }
+
+    // List device types known to Voltha
+    rpc ListDeviceTypes(google.protobuf.Empty) returns(DeviceTypes) {
+        option (google.api.http) = {
+            get: "/api/v1/device_types"
+        };
+    }
+
+    // Get additional information on a device type
+    rpc GetDeviceType(ID) returns(DeviceType) {
+        option (google.api.http) = {
+            get: "/api/v1/device_types/{id}"
+        };
+    }
+
+    // List all device sharding groups
+    rpc ListDeviceGroups(google.protobuf.Empty) returns(DeviceGroups) {
+        option (google.api.http) = {
+            get: "/api/v1/device_groups"
+        };
+    }
+
+    // Get additional information on a device group
+    rpc GetDeviceGroup(ID) returns(DeviceGroup) {
+        option (google.api.http) = {
+            get: "/api/v1/device_groups/{id}"
+        };
+    }
+
+}
+
+/*
+ * Per-instance APIs
+ *
+ * These APIs are always served locally by the Voltha instance on which the
+ * call is made.
+ */
+service VolthaLocalService {
+
+    // Get information on this Voltha instance
+    rpc GetVolthaInstance(google.protobuf.Empty) returns(VolthaInstance) {
+        option (google.api.http) = {
+            get: "/api/v1/local"
+        };
+    }
+
+    // Get the health state of the Voltha instance
+    rpc GetHealth(google.protobuf.Empty) returns(HealthStatus) {
+        option (google.api.http) = {
+            get: "/api/v1/local/health"
+        };
+    }
+
+    // List all active adapters (plugins) in this Voltha instance
+    rpc ListAdapters(google.protobuf.Empty) returns(Adapters) {
+        option (google.api.http) = {
+            get: "/api/v1/local/adapters"
+        };
+    }
+
+    // List all logical devices managed by this Voltha instance
+    rpc ListLogicalDevices(google.protobuf.Empty) returns(LogicalDevices) {
+        option (google.api.http) = {
+            get: "/api/v1/local/logical_devices"
+        };
+    }
+
+    // Get additional information on given logical device
+    rpc GetLogicalDevice(ID) returns(LogicalDevice) {
+        option (google.api.http) = {
+            get: "/api/v1/local/logical_devices/{id}"
+        };
+    }
+
+    // List ports of a logical device
+    rpc ListLogicalDevicePorts(ID) returns(LogicalPorts) {
+        option (google.api.http) = {
+            get: "/api/v1/local/logical_devices/{id}/ports"
+        };
+    }
+
+    // List all flows of a logical device
+    rpc ListLogicalDeviceFlows(ID) returns(openflow_13.Flows) {
+        option (google.api.http) = {
+            get: "/api/v1/local/logical_devices/{id}/flows"
+        };
+    }
+
+    // Update flow table for logical device
+    rpc UpdateLogicalDeviceFlowTable(openflow_13.FlowTableUpdate)
+            returns(google.protobuf.Empty) {
+        option (google.api.http) = {
+            post: "/api/v1/local/logical_devices/{id}/flows"
+            body: "*"
+        };
+    }
+
+    // List all flow groups of a logical device
+    rpc ListLogicalDeviceFlowGroups(ID) returns(openflow_13.FlowGroups) {
+        option (google.api.http) = {
+            get: "/api/v1/local/logical_devices/{id}/flow_groups"
+        };
+    }
+
+    // Update group table for logical device
+    rpc UpdateLogicalDeviceFlowGroupTable(openflow_13.FlowGroupTableUpdate)
+            returns(google.protobuf.Empty) {
+        option (google.api.http) = {
+            post: "/api/v1/local/logical_devices/{id}/flow_groups"
+            body: "*"
+        };
+    }
+
+    // List all physical devices managed by this Voltha instance
+    rpc ListDevices(google.protobuf.Empty) returns(Devices) {
+        option (google.api.http) = {
+            get: "/api/v1/local/devices"
+        };
+    }
+
+    // Get additional information on this device
+    rpc GetDevice(ID) returns(Device) {
+        option (google.api.http) = {
+            get: "/api/v1/local/devices/{id}"
+        };
+    }
+
+    // Pre-provision a new physical device
+    rpc CreateDevice(Device) returns(Device) {
+        option (google.api.http) = {
+            post: "/api/v1/local/devices"
+            body: "*"
+        };
+    }
+
+    // Activate a pre-provisioned device
+    rpc ActivateDevice(ID) returns(google.protobuf.Empty) {
+        option (google.api.http) = {
+            post: "/api/v1/local/devices/{id}/activate"
+            body: "{}"
+        };
+    }
+
+    // List ports of a device
+    rpc ListDevicePorts(ID) returns(Ports) {
+        option (google.api.http) = {
+            get: "/api/v1/local/devices/{id}/ports"
+        };
+    }
+
+    // List all flows of a device
+    rpc ListDeviceFlows(ID) returns(openflow_13.Flows) {
+        option (google.api.http) = {
+            get: "/api/v1/local/devices/{id}/flows"
+        };
+    }
+
+    // List all flow groups of a device
+    rpc ListDeviceFlowGroups(ID) returns(openflow_13.FlowGroups) {
+        option (google.api.http) = {
+            get: "/api/v1/local/devices/{id}/flow_groups"
+        };
+    }
+
+    // List device types know to Voltha instance
+    rpc ListDeviceTypes(google.protobuf.Empty) returns(DeviceTypes) {
+        option (google.api.http) = {
+            get: "/api/v1/local/device_types"
+        };
+    }
+
+    // Get additional information on given device type
+    rpc GetDeviceType(ID) returns(DeviceType) {
+        option (google.api.http) = {
+            get: "/api/v1/local/device_types/{id}"
+        };
+    }
+
+    // List device sharding groups managed by this Voltha instance
+    rpc ListDeviceGroups(google.protobuf.Empty) returns(DeviceGroups) {
+        option (google.api.http) = {
+            get: "/api/v1/local/device_groups"
+        };
+    }
+
+    // Get more information on given device shard
+    rpc GetDeviceGroup(ID) returns(DeviceGroup) {
+        option (google.api.http) = {
+            get: "/api/v1/local/device_groups/{id}"
+        };
+    }
+
+    // Stream control packets to the dataplane
+    rpc StreamPacketsOut(stream openflow_13.PacketOut)
+        returns(google.protobuf.Empty) {
+        // This does not have an HTTP representation
+    }
+
+    // Receive control packet stream
+    rpc ReceivePacketsIn(google.protobuf.Empty)
+        returns(stream openflow_13.PacketIn) {
+        // This does not have an HTTP representation
+    }
+
+}
diff --git a/experiments/netconf/proto2yang/voltha_orig.proto b/experiments/netconf/proto2yang/voltha_orig.proto
new file mode 100644
index 0000000..f0d9aff
--- /dev/null
+++ b/experiments/netconf/proto2yang/voltha_orig.proto
@@ -0,0 +1,421 @@
+/*
+ * Top-level Voltha API definition
+ *
+ * For details, see individual definition files.
+ */
+
+syntax = "proto3";
+
+package voltha;
+
+import "google/protobuf/empty.proto";
+import "google/api/annotations.proto";
+
+import public "meta.proto";
+import public "common.proto";
+import public "health.proto";
+import public "logical_device.proto";
+import public "device.proto";
+import public "adapter.proto";
+import public "openflow_13.proto";
+
+option java_package = "org.opencord.voltha";
+option java_outer_classname = "VolthaProtos";
+option csharp_namespace = "Opencord.Voltha.Voltha";
+
+message DeviceGroup {
+
+    string id = 1 [(access) = READ_ONLY];
+
+    repeated LogicalDevice logical_devices = 2 [(child_node) = {key: "id"}];
+
+    repeated Device devices = 3 [(child_node) = {key: "id"}];
+}
+
+message DeviceGroups {
+    repeated DeviceGroup items = 1;
+}
+
+// Top-level (root) node for a Voltha Instance
+message VolthaInstance {
+
+    string instance_id = 1  [(access) = READ_ONLY];
+
+    string version = 2 [(access) = READ_ONLY];
+
+    LogLevel.LogLevel log_level = 3;
+
+    HealthStatus health = 10 [(child_node) = {}];
+
+    repeated Adapter adapters = 11 [(child_node) = {key: "id" }];
+
+    repeated LogicalDevice logical_devices = 12 [(child_node) = {key: "id"}];
+
+    repeated Device devices = 13 [(child_node) = {key: "id"}];
+
+    repeated DeviceType device_types = 14 [(child_node) = {key: "id"}];
+
+    repeated DeviceGroup device_groups = 15 [(child_node) = {key: "id"}];
+}
+
+message VolthaInstances {
+    repeated string items = 1;
+}
+
+// Voltha representing the entire Voltha cluster
+message Voltha {
+
+    string version = 1 [(access) = READ_ONLY];
+
+    LogLevel.LogLevel log_level = 2;
+
+    repeated VolthaInstance instances = 3 [(child_node) = {key: "instance_id"}];
+
+    repeated Adapter adapters = 11 [(child_node) = {key: "id"}];
+
+    repeated LogicalDevice logical_devices = 12 [(child_node) = {key: "id"}];
+
+    repeated Device devices = 13 [(child_node) = {key: "id"}];
+
+    repeated DeviceGroup device_groups = 15 [(child_node) = {key: "id"}];
+
+}
+
+
+/*
+ * Cluster-wide Voltha APIs
+ *
+ * These APIs are potentially dispatched to the leader of the Voltha cluster,
+ * to a specific Voltha instance which owns the given device or logical device.
+ *
+ */
+service VolthaGlobalService {
+
+    // Get high level information on the Voltha cluster
+    rpc GetVoltha(google.protobuf.Empty) returns(Voltha) {
+        option (google.api.http) = {
+            get: "/api/v1"
+        };
+    }
+
+    // List all Voltha cluster instances
+    rpc ListVolthaInstances(google.protobuf.Empty) returns(VolthaInstances) {
+        option (google.api.http) = {
+            get: "/api/v1/instances"
+        };
+    }
+
+    // Get details on a Voltha cluster instance
+    rpc GetVolthaInstance(ID) returns(VolthaInstance) {
+        option (google.api.http) = {
+            get: "/api/v1/instances/{id}"
+        };
+    }
+
+    // List all logical devices managed by the Voltha cluster
+    rpc ListLogicalDevices(google.protobuf.Empty) returns(LogicalDevices) {
+        option (google.api.http) = {
+            get: "/api/v1/logical_devices"
+        };
+    }
+
+    // Get additional information on a given logical device
+    rpc GetLogicalDevice(ID) returns(LogicalDevice) {
+        option (google.api.http) = {
+            get: "/api/v1/logical_devices/{id}"
+        };
+    }
+
+    // List ports of a logical device
+    rpc ListLogicalDevicePorts(ID) returns(LogicalPorts) {
+        option (google.api.http) = {
+            get: "/api/v1/logical_devices/{id}/ports"
+        };
+    }
+
+    // List all flows of a logical device
+    rpc ListLogicalDeviceFlows(ID) returns(openflow_13.Flows) {
+        option (google.api.http) = {
+            get: "/api/v1/logical_devices/{id}/flows"
+        };
+    }
+
+    // Update flow table for logical device
+    rpc UpdateLogicalDeviceFlowTable(openflow_13.FlowTableUpdate)
+            returns(google.protobuf.Empty) {
+        option (google.api.http) = {
+            post: "/api/v1/logical_devices/{id}/flows"
+            body: "*"
+        };
+    }
+
+    // List all flow groups of a logical device
+    rpc ListLogicalDeviceFlowGroups(ID) returns(openflow_13.FlowGroups) {
+        option (google.api.http) = {
+            get: "/api/v1/logical_devices/{id}/flow_groups"
+        };
+    }
+
+    // Update group table for device
+    rpc UpdateLogicalDeviceFlowGroupTable(openflow_13.FlowGroupTableUpdate)
+            returns(google.protobuf.Empty) {
+        option (google.api.http) = {
+            post: "/api/v1/logical_devices/{id}/flow_groups"
+            body: "*"
+        };
+    }
+
+    // List all physical devices controlled by the Voltha cluster
+    rpc ListDevices(google.protobuf.Empty) returns(Devices) {
+        option (google.api.http) = {
+            get: "/api/v1/devices"
+        };
+    }
+
+    // Get more information on a given physical device
+    rpc GetDevice(ID) returns(Device) {
+        option (google.api.http) = {
+            get: "/api/v1/devices/{id}"
+        };
+    }
+
+    // Pre-provision a new physical device
+    rpc CreateDevice(Device) returns(Device) {
+        option (google.api.http) = {
+            post: "/api/v1/devices"
+            body: "*"
+        };
+    }
+
+    // Activate a pre-provisioned device
+    rpc ActivateDevice(ID) returns(google.protobuf.Empty) {
+        option (google.api.http) = {
+            post: "/api/v1/devices/{id}/activate"
+        };
+    }
+
+    // List ports of a device
+    rpc ListDevicePorts(ID) returns(Ports) {
+        option (google.api.http) = {
+            get: "/api/v1/devices/{id}/ports"
+        };
+    }
+
+    // List all flows of a device
+    rpc ListDeviceFlows(ID) returns(openflow_13.Flows) {
+        option (google.api.http) = {
+            get: "/api/v1/devices/{id}/flows"
+        };
+    }
+
+    // List all flow groups of a device
+    rpc ListDeviceFlowGroups(ID) returns(openflow_13.FlowGroups) {
+        option (google.api.http) = {
+            get: "/api/v1/devices/{id}/flow_groups"
+        };
+    }
+
+    // List device types known to Voltha
+    rpc ListDeviceTypes(google.protobuf.Empty) returns(DeviceTypes) {
+        option (google.api.http) = {
+            get: "/api/v1/device_types"
+        };
+    }
+
+    // Get additional information on a device type
+    rpc GetDeviceType(ID) returns(DeviceType) {
+        option (google.api.http) = {
+            get: "/api/v1/device_types/{id}"
+        };
+    }
+
+    // List all device sharding groups
+    rpc ListDeviceGroups(google.protobuf.Empty) returns(DeviceGroups) {
+        option (google.api.http) = {
+            get: "/api/v1/device_groups"
+        };
+    }
+
+    // Get additional information on a device group
+    rpc GetDeviceGroup(ID) returns(DeviceGroup) {
+        option (google.api.http) = {
+            get: "/api/v1/device_groups/{id}"
+        };
+    }
+
+}
+
+/*
+ * Per-instance APIs
+ *
+ * These APIs are always served locally by the Voltha instance on which the
+ * call is made.
+ */
+service VolthaLocalService {
+
+    // Get information on this Voltha instance
+    rpc GetVolthaInstance(google.protobuf.Empty) returns(VolthaInstance) {
+        option (google.api.http) = {
+            get: "/api/v1/local"
+        };
+    }
+
+    // Get the health state of the Voltha instance
+    rpc GetHealth(google.protobuf.Empty) returns(HealthStatus) {
+        option (google.api.http) = {
+            get: "/api/v1/local/health"
+        };
+    }
+
+    // List all active adapters (plugins) in this Voltha instance
+    rpc ListAdapters(google.protobuf.Empty) returns(Adapters) {
+        option (google.api.http) = {
+            get: "/api/v1/local/adapters"
+        };
+    }
+
+    // List all logical devices managed by this Voltha instance
+    rpc ListLogicalDevices(google.protobuf.Empty) returns(LogicalDevices) {
+        option (google.api.http) = {
+            get: "/api/v1/local/logical_devices"
+        };
+    }
+
+    // Get additional information on given logical device
+    rpc GetLogicalDevice(ID) returns(LogicalDevice) {
+        option (google.api.http) = {
+            get: "/api/v1/local/logical_devices/{id}"
+        };
+    }
+
+    // List ports of a logical device
+    rpc ListLogicalDevicePorts(ID) returns(LogicalPorts) {
+        option (google.api.http) = {
+            get: "/api/v1/local/logical_devices/{id}/ports"
+        };
+    }
+
+    // List all flows of a logical device
+    rpc ListLogicalDeviceFlows(ID) returns(openflow_13.Flows) {
+        option (google.api.http) = {
+            get: "/api/v1/local/logical_devices/{id}/flows"
+        };
+    }
+
+    // Update flow table for logical device
+    rpc UpdateLogicalDeviceFlowTable(openflow_13.FlowTableUpdate)
+            returns(google.protobuf.Empty) {
+        option (google.api.http) = {
+            post: "/api/v1/local/logical_devices/{id}/flows"
+            body: "*"
+        };
+    }
+
+    // List all flow groups of a logical device
+    rpc ListLogicalDeviceFlowGroups(ID) returns(openflow_13.FlowGroups) {
+        option (google.api.http) = {
+            get: "/api/v1/local/logical_devices/{id}/flow_groups"
+        };
+    }
+
+    // Update group table for logical device
+    rpc UpdateLogicalDeviceFlowGroupTable(openflow_13.FlowGroupTableUpdate)
+            returns(google.protobuf.Empty) {
+        option (google.api.http) = {
+            post: "/api/v1/local/logical_devices/{id}/flow_groups"
+            body: "*"
+        };
+    }
+
+    // List all physical devices managed by this Voltha instance
+    rpc ListDevices(google.protobuf.Empty) returns(Devices) {
+        option (google.api.http) = {
+            get: "/api/v1/local/devices"
+        };
+    }
+
+    // Get additional information on this device
+    rpc GetDevice(ID) returns(Device) {
+        option (google.api.http) = {
+            get: "/api/v1/local/devices/{id}"
+        };
+    }
+
+    // Pre-provision a new physical device
+    rpc CreateDevice(Device) returns(Device) {
+        option (google.api.http) = {
+            post: "/api/v1/local/devices"
+            body: "*"
+        };
+    }
+
+    // Activate a pre-provisioned device
+    rpc ActivateDevice(ID) returns(google.protobuf.Empty) {
+        option (google.api.http) = {
+            post: "/api/v1/local/devices/{id}/activate"
+            body: "{}"
+        };
+    }
+
+    // List ports of a device
+    rpc ListDevicePorts(ID) returns(Ports) {
+        option (google.api.http) = {
+            get: "/api/v1/local/devices/{id}/ports"
+        };
+    }
+
+    // List all flows of a device
+    rpc ListDeviceFlows(ID) returns(openflow_13.Flows) {
+        option (google.api.http) = {
+            get: "/api/v1/local/devices/{id}/flows"
+        };
+    }
+
+    // List all flow groups of a device
+    rpc ListDeviceFlowGroups(ID) returns(openflow_13.FlowGroups) {
+        option (google.api.http) = {
+            get: "/api/v1/local/devices/{id}/flow_groups"
+        };
+    }
+
+    // List device types know to Voltha instance
+    rpc ListDeviceTypes(google.protobuf.Empty) returns(DeviceTypes) {
+        option (google.api.http) = {
+            get: "/api/v1/local/device_types"
+        };
+    }
+
+    // Get additional information on given device type
+    rpc GetDeviceType(ID) returns(DeviceType) {
+        option (google.api.http) = {
+            get: "/api/v1/local/device_types/{id}"
+        };
+    }
+
+    // List device sharding groups managed by this Voltha instance
+    rpc ListDeviceGroups(google.protobuf.Empty) returns(DeviceGroups) {
+        option (google.api.http) = {
+            get: "/api/v1/local/device_groups"
+        };
+    }
+
+    // Get more information on given device shard
+    rpc GetDeviceGroup(ID) returns(DeviceGroup) {
+        option (google.api.http) = {
+            get: "/api/v1/local/device_groups/{id}"
+        };
+    }
+
+    // Stream control packets to the dataplane
+    rpc StreamPacketsOut(stream openflow_13.PacketOut)
+        returns(google.protobuf.Empty) {
+        // This does not have an HTTP representation
+    }
+
+    // Receive control packet stream
+    rpc ReceivePacketsIn(google.protobuf.Empty)
+        returns(stream openflow_13.PacketIn) {
+        // This does not have an HTTP representation
+    }
+
+}