VOL-2927 convert to static protos

Change-Id: If08aec0b1fb84fc54f7f62d5e4ede8ad4a9db80f
diff --git a/pkg/filter/filter.go b/pkg/filter/filter.go
index 0c18394..f566d94 100644
--- a/pkg/filter/filter.go
+++ b/pkg/filter/filter.go
@@ -141,6 +141,11 @@
 func (f Filter) Evaluate(item interface{}) bool {
 	val := reflect.ValueOf(item)
 
+	// If we have been given a pointer, then deference it
+	if val.Kind() == reflect.Ptr {
+		val = reflect.Indirect(val)
+	}
+
 	for k, v := range f {
 		field := val.FieldByName(k)
 		if !field.IsValid() {
diff --git a/pkg/format/formatter.go b/pkg/format/formatter.go
index c42b8ea..2b744d1 100644
--- a/pkg/format/formatter.go
+++ b/pkg/format/formatter.go
@@ -92,7 +92,11 @@
 		format = Format(strings.TrimPrefix(string(f), "table"))
 	}
 
-	tmpl, err := template.New("output").Parse(string(format))
+	funcmap := template.FuncMap{
+		"timestamp": formatTimestamp,
+		"since":     formatSince}
+
+	tmpl, err := template.New("output").Funcs(funcmap).Parse(string(format))
 	if err != nil {
 		return err
 	}
diff --git a/pkg/format/formatter_funcs.go b/pkg/format/formatter_funcs.go
new file mode 100644
index 0000000..6d10514
--- /dev/null
+++ b/pkg/format/formatter_funcs.go
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2019-present Ciena Corporation
+ *
+ * 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.
+ */
+package format
+
+import (
+	"github.com/golang/protobuf/ptypes"
+	timestamppb "github.com/golang/protobuf/ptypes/timestamp"
+	"time"
+)
+
+// formats a Timestamp proto as a RFC3339 date string
+func formatTimestamp(tsproto *timestamppb.Timestamp) (string, error) {
+	if tsproto == nil {
+		return "", nil
+	}
+	ts, err := ptypes.Timestamp(tsproto)
+	if err != nil {
+		return "", err
+	}
+	return ts.Truncate(time.Second).Format(time.RFC3339), nil
+}
+
+// Computes the age of a timestamp and returns it in HMS format
+func formatSince(tsproto *timestamppb.Timestamp) (string, error) {
+	if tsproto == nil {
+		return "", nil
+	}
+	ts, err := ptypes.Timestamp(tsproto)
+	if err != nil {
+		return "", err
+	}
+	return time.Since(ts).Truncate(time.Second).String(), nil
+}
diff --git a/pkg/model/adapter.go b/pkg/model/adapter.go
deleted file mode 100644
index 711f8aa..0000000
--- a/pkg/model/adapter.go
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2019-present Ciena Corporation
- *
- * 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.
- */
-package model
-
-import (
-	"github.com/golang/protobuf/ptypes"
-	"github.com/golang/protobuf/ptypes/timestamp"
-	"github.com/jhump/protoreflect/dynamic"
-	"time"
-)
-
-type Adapter struct {
-	Id                     string
-	Vendor                 string
-	Version                string
-	LogLevel               string
-	LastCommunication      string
-	SinceLastCommunication string
-	CurrentReplica         int32
-	TotalReplicas          int32
-	Endpoint               string
-	Type                   string
-}
-
-func (adapter *Adapter) PopulateFrom(val *dynamic.Message) {
-
-	adapter.Id = val.GetFieldByName("id").(string)
-	adapter.Vendor = val.GetFieldByName("vendor").(string)
-	adapter.Version = val.GetFieldByName("version").(string)
-
-	if value, err := val.TryGetFieldByName("currentReplica"); err != nil {
-		adapter.CurrentReplica = 0
-	} else {
-		adapter.CurrentReplica = value.(int32)
-	}
-	if value, err := val.TryGetFieldByName("totalReplicas"); err != nil {
-		adapter.TotalReplicas = 0
-	} else {
-		adapter.TotalReplicas = value.(int32)
-	}
-	if value, err := val.TryGetFieldByName("endpoint"); err != nil {
-		adapter.Endpoint = "UNKNOWN"
-	} else {
-		adapter.Endpoint = value.(string)
-	}
-	if value, err := val.TryGetFieldByName("type"); err != nil {
-		adapter.Type = "UNKNOWN"
-	} else {
-		adapter.Type = value.(string)
-	}
-
-	if lastCommunication, err := val.TryGetFieldByName("last_communication"); err != nil {
-		adapter.LastCommunication = "UNKNOWN"
-		adapter.SinceLastCommunication = "UNKNOWN"
-	} else {
-		if lastCommunication, err := ptypes.Timestamp(lastCommunication.(*timestamp.Timestamp)); err != nil {
-			adapter.LastCommunication = "NEVER"
-			adapter.SinceLastCommunication = "NEVER"
-		} else {
-			adapter.LastCommunication = lastCommunication.Truncate(time.Second).Format(time.RFC3339)
-			adapter.SinceLastCommunication = time.Since(lastCommunication).Truncate(time.Second).String()
-		}
-	}
-
-}
diff --git a/pkg/model/device.go b/pkg/model/device.go
deleted file mode 100644
index e307308..0000000
--- a/pkg/model/device.go
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright 2019-present Ciena Corporation
- *
- * 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.
- */
-package model
-
-import (
-	"github.com/jhump/protoreflect/dynamic"
-)
-
-type PeerPort struct {
-	DeviceId string `json:"deviceid"`
-	PortNo   uint32 `json:"portno"`
-}
-
-type ProxyAddress struct {
-	DeviceId           string `json:"deviceId"`
-	DeviceType         string `json:"devicetype,omitempty"`
-	ChannelId          uint32 `json:"channelid"`
-	ChannelGroupId     uint32 `json:"channelgroup"`
-	ChannelTermination string `json:"channeltermination,omitempty"`
-	OnuId              uint32 `json:"onuid"`
-	OnuSessionId       uint32 `json:"onusessionid"`
-}
-
-type Device struct {
-	Id              string        `json:"id"`
-	Type            string        `json:"type"`
-	Root            bool          `json:"root"`
-	ParentId        string        `json:"parentid"`
-	ParentPortNo    uint32        `json:"parentportno"`
-	Vendor          string        `json:"vendor"`
-	Model           string        `json:"model"`
-	HardwareVersion string        `json:"hardwareversion"`
-	FirmwareVersion string        `json:"firmwareversion"`
-	SerialNumber    string        `json:"serialnumber"`
-	VendorId        string        `json:"vendorid"`
-	Adapter         string        `json:"adapter"`
-	Vlan            uint32        `json:"vlan"`
-	MacAddress      string        `json:"macaddress"`
-	Address         string        `json:"address"`
-	ExtraArgs       string        `json:"extraargs"`
-	ProxyAddress    *ProxyAddress `json:"proxyaddress,omitempty"`
-	AdminState      string        `json:"adminstate"`
-	OperStatus      string        `json:"operstatus"`
-	Reason          string        `json:"reason"`
-	ConnectStatus   string        `json:"connectstatus"`
-	Ports           []DevicePort  `json:"ports"`
-	Flows           []Flow        `json:"flows"`
-}
-
-type DevicePort struct {
-	PortNo     uint32     `json:"portno"`
-	Label      string     `json:"label"`
-	Type       string     `json:"type"`
-	AdminState string     `json:"adminstate"`
-	OperStatus string     `json:"operstatus"`
-	DeviceId   string     `json:"deviceid"`
-	Peers      []PeerPort `json:"peers"`
-}
-
-func (d *Device) PopulateFrom(val *dynamic.Message) {
-	d.Id = val.GetFieldByName("id").(string)
-	d.Type = val.GetFieldByName("type").(string)
-	d.Root = val.GetFieldByName("root").(bool)
-	d.ParentId = val.GetFieldByName("parent_id").(string)
-	d.ParentPortNo = val.GetFieldByName("parent_port_no").(uint32)
-	d.Vendor = val.GetFieldByName("vendor").(string)
-	d.Model = val.GetFieldByName("model").(string)
-	d.HardwareVersion = val.GetFieldByName("hardware_version").(string)
-	d.FirmwareVersion = val.GetFieldByName("firmware_version").(string)
-	d.SerialNumber = val.GetFieldByName("serial_number").(string)
-	d.VendorId = val.GetFieldByName("vendor_id").(string)
-	d.Adapter = val.GetFieldByName("adapter").(string)
-	d.MacAddress = val.GetFieldByName("mac_address").(string)
-	d.Vlan = val.GetFieldByName("vlan").(uint32)
-	d.Address = val.GetFieldByName("host_and_port").(string)
-	if len(d.Address) == 0 {
-		d.Address = val.GetFieldByName("ipv4_address").(string)
-	}
-	if len(d.Address) == 0 {
-		d.Address = val.GetFieldByName("ipv6_address").(string)
-	}
-	if len(d.Address) == 0 {
-		d.Address = "unknown"
-	}
-	d.ExtraArgs = val.GetFieldByName("extra_args").(string)
-	proxy := val.GetFieldByName("proxy_address").(*dynamic.Message)
-	d.ProxyAddress = nil
-	if proxy != nil {
-		d.ProxyAddress = &ProxyAddress{
-			DeviceId:       proxy.GetFieldByName("device_id").(string),
-			ChannelId:      proxy.GetFieldByName("channel_id").(uint32),
-			ChannelGroupId: proxy.GetFieldByName("channel_group_id").(uint32),
-			OnuId:          proxy.GetFieldByName("onu_id").(uint32),
-			OnuSessionId:   proxy.GetFieldByName("onu_session_id").(uint32),
-		}
-		v, err := proxy.TryGetFieldByName("device_type")
-		if err == nil {
-			d.ProxyAddress.DeviceType = v.(string)
-		}
-		v, err = proxy.TryGetFieldByName("channel_termination")
-		if err == nil {
-			d.ProxyAddress.ChannelTermination = v.(string)
-		}
-	}
-
-	var err error
-	d.AdminState, err = GetEnumValue(val, "admin_state")
-	if err != nil {
-		d.AdminState = "UNKNOWN"
-	}
-
-	d.OperStatus, err = GetEnumValue(val, "oper_status")
-	if err != nil {
-		d.OperStatus = "UNKNOWN"
-	}
-
-	d.Reason = val.GetFieldByName("reason").(string)
-	d.ConnectStatus, err = GetEnumValue(val, "connect_status")
-	if err != nil {
-		d.ConnectStatus = "UNKNOWN"
-	}
-
-	ports := val.GetFieldByName("ports").([]interface{})
-	d.Ports = make([]DevicePort, len(ports))
-	for i, port := range ports {
-		d.Ports[i].PopulateFrom(port.(*dynamic.Message))
-	}
-	flows := val.GetFieldByName("flows").(*dynamic.Message)
-	if flows == nil {
-		d.Flows = make([]Flow, 0)
-	} else {
-		items := flows.GetFieldByName("items").([]interface{})
-		d.Flows = make([]Flow, len(items))
-		for i, flow := range items {
-			d.Flows[i].PopulateFrom(flow.(*dynamic.Message))
-		}
-	}
-}
-
-func (port *DevicePort) PopulateFrom(val *dynamic.Message) {
-	var err error
-	port.PortNo = val.GetFieldByName("port_no").(uint32)
-	port.Type, err = GetEnumValue(val, "type")
-	if err != nil {
-		port.Type = "UNKNOWN"
-	}
-	port.Label = val.GetFieldByName("label").(string)
-	port.AdminState, err = GetEnumValue(val, "admin_state")
-	if err != nil {
-		port.AdminState = "UNKNOWN"
-	}
-
-	port.OperStatus, err = GetEnumValue(val, "oper_status")
-	if err != nil {
-		port.OperStatus = "UNKNOWN"
-	}
-	port.DeviceId = val.GetFieldByName("device_id").(string)
-	peers := val.GetFieldByName("peers").([]interface{})
-	port.Peers = make([]PeerPort, len(peers))
-	for j, peer := range peers {
-		p := peer.(*dynamic.Message)
-		port.Peers[j].DeviceId = p.GetFieldByName("device_id").(string)
-		port.Peers[j].PortNo = p.GetFieldByName("port_no").(uint32)
-	}
-}
diff --git a/pkg/model/devicegroup.go b/pkg/model/devicegroup.go
deleted file mode 100644
index a433a08..0000000
--- a/pkg/model/devicegroup.go
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2019-present Ciena Corporation
- *
- * 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.
- */
-package model
-
-import (
-	"github.com/jhump/protoreflect/dynamic"
-)
-
-type DeviceGroup struct {
-	Id             string   `json:"id"`
-	LogicalDevices []string `json:"logicaldevices"`
-	Devices        []string `json:"devices"`
-}
-
-func getId(val *dynamic.Message) string {
-	return val.GetFieldByName("id").(string)
-}
-
-func (d *DeviceGroup) PopulateFrom(val *dynamic.Message) {
-	d.Id = val.GetFieldByName("id").(string)
-	logicaldevices := val.GetFieldByName("logical_devices").([]interface{})
-	d.LogicalDevices = make([]string, len(logicaldevices))
-	for i, logicaldevice := range logicaldevices {
-		d.LogicalDevices[i] = getId(logicaldevice.(*dynamic.Message))
-	}
-	devices := val.GetFieldByName("logical_devices").([]interface{})
-	d.Devices = make([]string, len(devices))
-	for i, device := range devices {
-		d.Devices[i] = getId(device.(*dynamic.Message))
-	}
-}
diff --git a/pkg/model/flow.go b/pkg/model/flow.go
index 52e968e..1a5f88b 100644
--- a/pkg/model/flow.go
+++ b/pkg/model/flow.go
@@ -17,7 +17,7 @@
 
 import (
 	"fmt"
-	"github.com/jhump/protoreflect/dynamic"
+	"github.com/opencord/voltha-protos/v3/go/openflow_13"
 )
 
 type FlowFieldFlag uint64
@@ -294,72 +294,69 @@
 	return fmt.Sprintf("%d", val)
 }
 
-func (f *Flow) PopulateFrom(val *dynamic.Message) {
+func (f *Flow) PopulateFromProto(flow *openflow_13.OfpFlowStats) {
 
 	f.Reset()
-	f.Id = fmt.Sprintf("%016x", val.GetFieldByName("id").(uint64))
-	f.TableId = val.GetFieldByName("table_id").(uint32)
-	f.Priority = val.GetFieldByName("priority").(uint32)
+	f.Id = fmt.Sprintf("%016x", flow.Id)
+	f.TableId = flow.TableId
+	f.Priority = flow.Priority
 	// mask the lower 8 for the cookie, why?
-	cookie := val.GetFieldByName("cookie").(uint64)
+	cookie := flow.Cookie
 	if cookie == 0 {
 		f.Cookie = "0"
 	} else {
-		f.Cookie = fmt.Sprintf("~%08x", val.GetFieldByName("cookie").(uint64)&0xffffffff)
+		f.Cookie = fmt.Sprintf("~%08x", flow.Cookie&0xffffffff)
 	}
-	f.DurationSec = val.GetFieldByName("duration_sec").(uint32)
-	f.DurationNsec = val.GetFieldByName("duration_nsec").(uint32)
-	f.IdleTimeout = val.GetFieldByName("idle_timeout").(uint32)
-	f.HardTimeout = val.GetFieldByName("hard_timeout").(uint32)
-	f.PacketCount = val.GetFieldByName("packet_count").(uint64)
-	f.ByteCount = val.GetFieldByName("byte_count").(uint64)
+	f.DurationSec = flow.DurationSec
+	f.DurationNsec = flow.DurationNsec
+	f.IdleTimeout = flow.IdleTimeout
+	f.HardTimeout = flow.HardTimeout
+	f.PacketCount = flow.PacketCount
+	f.ByteCount = flow.ByteCount
 	f.Set(FLOW_FIELD_HEADER | FLOW_FIELD_STATS)
 
-	match := val.GetFieldByName("match").(*dynamic.Message)
-	fields := match.GetFieldByName("oxm_fields")
-	for _, ifield := range fields.([]interface{}) {
-		field := ifield.(*dynamic.Message)
-
+	for _, field := range flow.Match.OxmFields {
 		// Only support OFPXMC_OPENFLOW_BASIC (0x8000)
-		if field.GetFieldByName("oxm_class").(int32) != 0x8000 {
+		if field.OxmClass != 0x8000 {
 			continue
 		}
 
-		basic := field.GetFieldByName("ofb_field").(*dynamic.Message)
-		switch basic.GetFieldByName("type").(int32) {
+		basic := field.GetOfbField()
+
+		switch basic.Type {
 		case 0: // IN_PORT
 			f.Set(FLOW_FIELD_IN_PORT)
-			f.InPort = fmt.Sprintf("%d", basic.GetFieldByName("port").(uint32))
+			f.InPort = fmt.Sprintf("%d", basic.GetPort())
 		case 2: // METADATA
 			f.Set(FLOW_FIELD_METADATA)
-			f.Metadata = fmt.Sprintf("0x%016x", basic.GetFieldByName("table_metadata").(uint64))
+			f.Metadata = fmt.Sprintf("0x%016x", basic.GetTableMetadata())
 		case 5: // ETH_TYPE
 			f.Set(FLOW_FIELD_ETH_TYPE)
-			f.EthType = fmt.Sprintf("0x%04x", basic.GetFieldByName("eth_type").(uint32))
+			f.EthType = fmt.Sprintf("0x%04x", basic.GetEthType())
 		case 6: // VLAN_ID
 			f.Set(FLOW_FIELD_VLAN_ID)
-			vid := basic.GetFieldByName("vlan_vid").(uint32)
-			mask, errMaskGet := basic.TryGetFieldByName("vlan_vid_mask")
-			if vid == ReservedTransparentVlan && errMaskGet == nil && mask.(uint32) == ReservedTransparentVlan {
+			vid := basic.GetVlanVid()
+			mask := basic.GetVlanVidMask() // TODO: can this fail?
+			if vid == ReservedTransparentVlan && mask == ReservedTransparentVlan {
 				f.VlanId = "any"
 			} else {
 				f.VlanId = toVlanId(vid)
 			}
 		case 7: // VLAN_PCP
 			f.Set(FLOW_FIELD_VLAN_PCP)
-			f.VlanPcp = fmt.Sprintf("%d", basic.GetFieldByName("vlan_pcp").(uint32))
+			f.VlanPcp = fmt.Sprintf("%d", basic.GetVlanPcp())
 		case 10: // IP_PROTO
 			f.Set(FLOW_FIELD_IP_PROTO)
-			f.IpProto = fmt.Sprintf("%d", basic.GetFieldByName("ip_proto").(uint32))
+			f.IpProto = fmt.Sprintf("%d", basic.GetIpProto())
 		case 15: // UDP_SRC
 			f.Set(FLOW_FIELD_UDP_SRC)
-			f.UdpSrc = fmt.Sprintf("%d", basic.GetFieldByName("udp_src").(uint32))
+			f.UdpSrc = fmt.Sprintf("%d", basic.GetUdpSrc())
 		case 16: // UDP_DST
 			f.Set(FLOW_FIELD_UDP_DST)
-			f.UdpDst = fmt.Sprintf("%d", basic.GetFieldByName("udp_dst").(uint32))
+			f.UdpDst = fmt.Sprintf("%d", basic.GetUdpDst())
 		case 38: // TUNNEL_ID
 			f.Set(FLOW_FIELD_TUNNEL_ID)
-			f.TunnelId = fmt.Sprintf("%d", basic.GetFieldByName("tunnel_id").(uint64))
+			f.TunnelId = fmt.Sprintf("%d", basic.GetTunnelId())
 		default:
 			/*
 			 * For unsupported match types put them into an
@@ -368,35 +365,32 @@
 			 * having log messages.
 			 */
 			f.Set(FLOW_FIELD_UNSUPPORTED_MATCH)
-			f.UnsupportedMatch = appendInt32(f.UnsupportedMatch, basic.GetFieldByName("type").(int32))
+			f.UnsupportedMatch = appendInt32(f.UnsupportedMatch, int32(basic.Type))
 		}
 	}
-	for _, instruction := range val.GetFieldByName("instructions").([]interface{}) {
-		inst := instruction.(*dynamic.Message)
-		switch inst.GetFieldByName("type").(uint32) {
+	for _, inst := range flow.Instructions {
+		switch inst.Type {
 		case 1: // GOTO_TABLE
 			f.Set(FLOW_FIELD_GOTO_TABLE)
-			goto_table := inst.GetFieldByName("goto_table").(*dynamic.Message)
-			f.GotoTable = fmt.Sprintf("%d", goto_table.GetFieldByName("table_id").(uint32))
+			goto_table := inst.GetGotoTable()
+			f.GotoTable = fmt.Sprintf("%d", goto_table.TableId)
 		case 2: // WRITE_METADATA
 			f.Set(FLOW_FIELD_WRITE_METADATA)
-			meta := inst.GetFieldByName("write_metadata").(*dynamic.Message)
-			val := meta.GetFieldByName("metadata").(uint64)
-			mask := meta.GetFieldByName("metadata_mask").(uint64)
+			meta := inst.GetWriteMetadata()
+			val := meta.Metadata
+			mask := meta.MetadataMask
 			if mask != 0 {
 				f.WriteMetadata = fmt.Sprintf("0x%016x/0x%016x", val, mask)
 			} else {
 				f.WriteMetadata = fmt.Sprintf("0x%016x", val)
 			}
 		case 4: // APPLY_ACTIONS
-			actions := inst.GetFieldByName("actions").(*dynamic.Message)
-			for _, action := range actions.GetFieldByName("actions").([]interface{}) {
-				a := action.(*dynamic.Message)
-				switch a.GetFieldByName("type").(int32) {
+			for _, action := range inst.GetActions().Actions {
+				switch action.Type {
 				case 0: // OUTPUT
 					f.Set(FLOW_FIELD_OUTPUT)
-					output := a.GetFieldByName("output").(*dynamic.Message)
-					out := output.GetFieldByName("port").(uint32)
+					output := action.GetOutput()
+					out := output.Port
 					switch out & 0x7fffffff {
 					case 0:
 						f.Output = "INVALID"
@@ -417,28 +411,28 @@
 					case 0x7fffffff:
 						f.Output = "ANY"
 					default:
-						f.Output = fmt.Sprintf("%d", output.GetFieldByName("port").(uint32))
+						f.Output = fmt.Sprintf("%d", output.Port)
 					}
 				case 17: // PUSH_VLAN
 					f.Set(FLOW_FIELD_PUSH_VLAN_ID)
-					push := a.GetFieldByName("push").(*dynamic.Message)
-					f.PushVlanId = fmt.Sprintf("0x%x", push.GetFieldByName("ethertype").(uint32))
+					push := action.GetPush()
+					f.PushVlanId = fmt.Sprintf("0x%x", push.Ethertype)
 				case 18: // POP_VLAN
 					f.Set(FLOW_FIELD_POP_VLAN)
 					f.PopVlan = "yes"
 				case 25: // SET_FIELD
-					set := a.GetFieldByName("set_field").(*dynamic.Message).GetFieldByName("field").(*dynamic.Message)
+					set := action.GetSetField().Field
 
 					// Only support OFPXMC_OPENFLOW_BASIC (0x8000)
-					if set.GetFieldByName("oxm_class").(int32) != 0x8000 {
+					if set.OxmClass != 0x8000 {
 						continue
 					}
-					basic := set.GetFieldByName("ofb_field").(*dynamic.Message)
+					basic := set.GetOfbField()
 
-					switch basic.GetFieldByName("type").(int32) {
+					switch basic.Type {
 					case 6: // VLAN_ID
 						f.Set(FLOW_FIELD_SET_VLAN_ID)
-						f.SetVlanId = toVlanId(basic.GetFieldByName("vlan_vid").(uint32))
+						f.SetVlanId = toVlanId(basic.GetVlanVid())
 					default: // Unsupported
 						/*
 						 * For unsupported match types put them into an
@@ -448,7 +442,7 @@
 						 */
 						f.Set(FLOW_FIELD_UNSUPPORTED_SET_FIELD)
 						f.UnsupportedSetField = appendInt32(f.UnsupportedSetField,
-							basic.GetFieldByName("type").(int32))
+							int32(basic.Type))
 					}
 				default: // Unsupported
 					/*
@@ -459,7 +453,7 @@
 					 */
 					f.Set(FLOW_FIELD_UNSUPPORTED_ACTION)
 					f.UnsupportedAction = appendInt32(f.UnsupportedAction,
-						a.GetFieldByName("type").(int32))
+						int32(action.Type))
 				}
 			}
 		case 5: // CLEAR_ACTIONS
@@ -467,9 +461,9 @@
 			f.Set(FLOW_FIELD_CLEAR_ACTIONS)
 			f.ClearActions = "[]"
 		case 6: // METER
-			meter := inst.GetFieldByName("meter").(*dynamic.Message)
+			meter := inst.GetMeter()
 			f.Set(FLOW_FIELD_METER)
-			f.MeterId = fmt.Sprintf("%d", meter.GetFieldByName("meter_id").(uint32))
+			f.MeterId = fmt.Sprintf("%d", meter.MeterId)
 		default: // Unsupported
 			/*
 			 * For unsupported match types put them into an
@@ -479,7 +473,7 @@
 			 */
 			f.Set(FLOW_FIELD_UNSUPPORTED_INSTRUCTION)
 			f.UnsupportedInstruction = appendUint32(f.UnsupportedInstruction,
-				inst.GetFieldByName("type").(uint32))
+				uint32(inst.Type))
 		}
 	}
 }
diff --git a/pkg/model/logicaldevice.go b/pkg/model/logicaldevice.go
deleted file mode 100644
index 6afa40f..0000000
--- a/pkg/model/logicaldevice.go
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2019-present Ciena Corporation
- *
- * 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.
- */
-package model
-
-import (
-	"fmt"
-	"github.com/jhump/protoreflect/dynamic"
-	"strings"
-)
-
-type LogicalDevice struct {
-	Id           string `json:"id"`
-	DatapathId   string `json:"datapathid"`
-	RootDeviceId string `json:"rootdeviceid"`
-	SerialNumber string `json:"serialnumber"`
-	Features     struct {
-		NBuffers     uint32 `json:"nbuffers"`
-		NTables      uint32 `json:"ntables"`
-		Capabilities string `json:"capabilities"`
-	} `json:"features"`
-	Ports []LogicalPort `json:"ports"`
-	Flows []Flow        `json:"flows"`
-}
-
-type LogicalPort struct {
-	Id           string `json:"id"`
-	DeviceId     string `json:"deviceid"`
-	DevicePortNo uint32 `json:"deviceportno"`
-	RootPort     bool   `json:"rootport"`
-	Openflow     struct {
-		PortNo   uint32 `json:"portno"`
-		HwAddr   string `json:"hwaddr"`
-		Name     string `json:"name"`
-		Config   string `json:"config"`
-		State    string `json:"state"`
-		Features struct {
-			Advertised string `json:"advertised"`
-			Current    string `json:"current"`
-			Supported  string `json:"supported"`
-			Peer       string `json:"peer"`
-		} `json:"features"`
-		Bitrate struct {
-			Current uint32 `json:"current"`
-			Max     uint32 `json:"max"`
-		}
-	} `json:"openflow"`
-}
-
-func (device *LogicalDevice) PopulateFrom(val *dynamic.Message) {
-	device.Id = val.GetFieldByName("id").(string)
-	device.DatapathId = fmt.Sprintf("%016x", val.GetFieldByName("datapath_id").(uint64))
-	device.RootDeviceId = val.GetFieldByName("root_device_id").(string)
-	desc := val.GetFieldByName("desc").(*dynamic.Message)
-	device.SerialNumber = desc.GetFieldByName("serial_num").(string)
-	features := val.GetFieldByName("switch_features").(*dynamic.Message)
-	device.Features.NBuffers = features.GetFieldByName("n_buffers").(uint32)
-	device.Features.NTables = features.GetFieldByName("n_tables").(uint32)
-	device.Features.Capabilities = fmt.Sprintf("0x%08x", features.GetFieldByName("capabilities").(uint32))
-
-	ports := val.GetFieldByName("ports").([]interface{})
-	device.Ports = make([]LogicalPort, len(ports))
-	for i, port := range ports {
-		device.Ports[i].PopulateFrom(port.(*dynamic.Message))
-	}
-
-	flows := val.GetFieldByName("flows").(*dynamic.Message)
-	if flows == nil {
-		device.Flows = make([]Flow, 0)
-	} else {
-		items := flows.GetFieldByName("items").([]interface{})
-		device.Flows = make([]Flow, len(items))
-		for i, flow := range items {
-			device.Flows[i].PopulateFrom(flow.(*dynamic.Message))
-		}
-	}
-}
-
-func (port *LogicalPort) PopulateFrom(val *dynamic.Message) {
-	port.Id = val.GetFieldByName("id").(string)
-	port.DeviceId = val.GetFieldByName("device_id").(string)
-	port.DevicePortNo = val.GetFieldByName("device_port_no").(uint32)
-	port.RootPort = val.GetFieldByName("root_port").(bool)
-	ofp := val.GetFieldByName("ofp_port").(*dynamic.Message)
-	hw := strings.Builder{}
-	first := true
-	for _, b := range ofp.GetFieldByName("hw_addr").([]interface{}) {
-		if !first {
-			hw.WriteString(":")
-		}
-		first = false
-		hw.WriteString(fmt.Sprintf("%02x", b))
-	}
-	port.Openflow.HwAddr = hw.String()
-	port.Openflow.PortNo = ofp.GetFieldByName("port_no").(uint32)
-	port.Openflow.Name = ofp.GetFieldByName("name").(string)
-	port.Openflow.Config = fmt.Sprintf("0x%08x", ofp.GetFieldByName("config").(uint32))
-	port.Openflow.State = fmt.Sprintf("0x%08x", ofp.GetFieldByName("state").(uint32))
-	port.Openflow.Features.Current = fmt.Sprintf("0x%08x", ofp.GetFieldByName("curr").(uint32))
-	port.Openflow.Features.Advertised = fmt.Sprintf("0x%08x", ofp.GetFieldByName("advertised").(uint32))
-	port.Openflow.Features.Supported = fmt.Sprintf("0x%08x", ofp.GetFieldByName("supported").(uint32))
-	port.Openflow.Features.Peer = fmt.Sprintf("0x%08x", ofp.GetFieldByName("peer").(uint32))
-	port.Openflow.Bitrate.Current = ofp.GetFieldByName("curr_speed").(uint32)
-	port.Openflow.Bitrate.Max = ofp.GetFieldByName("max_speed").(uint32)
-}
diff --git a/pkg/model/returnvalues.go b/pkg/model/returnvalues.go
deleted file mode 100755
index 88fa2e5..0000000
--- a/pkg/model/returnvalues.go
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2019-present Ciena Corporation
- *
- * 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.
- */
-package model
-
-import (
-	"github.com/jhump/protoreflect/desc"
-	"github.com/jhump/protoreflect/dynamic"
-)
-
-type ReturnValueRow struct {
-	Name   string      `json:"name"`
-	Result interface{} `json:"result"`
-}
-
-type ReturnValues struct {
-	Set         uint32 `json:"set"`
-	Unsupported uint32 `json:"unsupported"`
-	Error       uint32 `json:"error"`
-	Distance    uint32 `json:"distance"`
-}
-
-func (r *ReturnValues) PopulateFrom(val *dynamic.Message) {
-	r.Set = val.GetFieldByName("Set").(uint32)
-	r.Unsupported = val.GetFieldByName("Unsupported").(uint32)
-	r.Error = val.GetFieldByName("Error").(uint32)
-	r.Distance = val.GetFieldByName("Distance").(uint32)
-}
-
-// Given a list of allowed enum values, check each one of the values against the
-// bitmaps, and fill out an array of result rows as follows:
-//    "Error", if the enum is set in the Error bitmap
-//    "Unsupported", if the enum is set in the Unsupported bitmap
-//    An interface containing the value, if the enum is set in the Set bitmap
-
-func (r *ReturnValues) GetKeyValuePairs(enumValues []*desc.EnumValueDescriptor) []ReturnValueRow {
-	var rows []ReturnValueRow
-
-	for _, v := range enumValues {
-		num := uint32(v.GetNumber())
-		if num == 0 {
-			// EMPTY is not a real value
-			continue
-		}
-		name := v.GetName()
-		if (r.Error & num) != 0 {
-			row := ReturnValueRow{Name: name, Result: "Error"}
-			rows = append(rows, row)
-		}
-		if (r.Unsupported & num) != 0 {
-			row := ReturnValueRow{Name: name, Result: "Unsupported"}
-			rows = append(rows, row)
-		}
-		if (r.Set & num) != 0 {
-			switch name {
-			case "DISTANCE":
-				row := ReturnValueRow{Name: name, Result: r.Distance}
-				rows = append(rows, row)
-			default:
-				row := ReturnValueRow{Name: name, Result: "Unimplemented-in-voltctl"}
-				rows = append(rows, row)
-			}
-		}
-	}
-
-	return rows
-}