diff --git a/vendor/github.com/opencord/omci-lib-go/messagetypes.go b/vendor/github.com/opencord/omci-lib-go/messagetypes.go
new file mode 100644
index 0000000..553b7f3
--- /dev/null
+++ b/vendor/github.com/opencord/omci-lib-go/messagetypes.go
@@ -0,0 +1,3524 @@
+/*
+ * Copyright (c) 2018 - present.  Boling Consulting Solutions (bcsw.net)
+ * Copyright 2020-present Open Networking Foundation
+
+ * 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 omci
+
+import (
+	"encoding/binary"
+	"errors"
+	"fmt"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/google/gopacket"
+)
+
+// MessageType is the OMCI Message Type or'ed with the AR/AK flags as appropriate.
+type MessageType byte
+
+const (
+	CreateRequestType                 = MessageType(byte(me.Create) | me.AR)
+	CreateResponseType                = MessageType(byte(me.Create) | me.AK)
+	DeleteRequestType                 = MessageType(byte(me.Delete) | me.AR)
+	DeleteResponseType                = MessageType(byte(me.Delete) | me.AK)
+	SetRequestType                    = MessageType(byte(me.Set) | me.AR)
+	SetResponseType                   = MessageType(byte(me.Set) | me.AK)
+	GetRequestType                    = MessageType(byte(me.Get) | me.AR)
+	GetResponseType                   = MessageType(byte(me.Get) | me.AK)
+	GetAllAlarmsRequestType           = MessageType(byte(me.GetAllAlarms) | me.AR)
+	GetAllAlarmsResponseType          = MessageType(byte(me.GetAllAlarms) | me.AK)
+	GetAllAlarmsNextRequestType       = MessageType(byte(me.GetAllAlarmsNext) | me.AR)
+	GetAllAlarmsNextResponseType      = MessageType(byte(me.GetAllAlarmsNext) | me.AK)
+	MibUploadRequestType              = MessageType(byte(me.MibUpload) | me.AR)
+	MibUploadResponseType             = MessageType(byte(me.MibUpload) | me.AK)
+	MibUploadNextRequestType          = MessageType(byte(me.MibUploadNext) | me.AR)
+	MibUploadNextResponseType         = MessageType(byte(me.MibUploadNext) | me.AK)
+	MibResetRequestType               = MessageType(byte(me.MibReset) | me.AR)
+	MibResetResponseType              = MessageType(byte(me.MibReset) | me.AK)
+	TestRequestType                   = MessageType(byte(me.Test) | me.AR)
+	TestResponseType                  = MessageType(byte(me.Test) | me.AK)
+	StartSoftwareDownloadRequestType  = MessageType(byte(me.StartSoftwareDownload) | me.AR)
+	StartSoftwareDownloadResponseType = MessageType(byte(me.StartSoftwareDownload) | me.AK)
+	DownloadSectionRequestType        = MessageType(byte(me.DownloadSection) | me.AR)
+	DownloadSectionResponseType       = MessageType(byte(me.DownloadSection) | me.AK)
+	EndSoftwareDownloadRequestType    = MessageType(byte(me.EndSoftwareDownload) | me.AR)
+	EndSoftwareDownloadResponseType   = MessageType(byte(me.EndSoftwareDownload) | me.AK)
+	ActivateSoftwareRequestType       = MessageType(byte(me.ActivateSoftware) | me.AR)
+	ActivateSoftwareResponseType      = MessageType(byte(me.ActivateSoftware) | me.AK)
+	CommitSoftwareRequestType         = MessageType(byte(me.CommitSoftware) | me.AR)
+	CommitSoftwareResponseType        = MessageType(byte(me.CommitSoftware) | me.AK)
+	SynchronizeTimeRequestType        = MessageType(byte(me.SynchronizeTime) | me.AR)
+	SynchronizeTimeResponseType       = MessageType(byte(me.SynchronizeTime) | me.AK)
+	RebootRequestType                 = MessageType(byte(me.Reboot) | me.AR)
+	RebootResponseType                = MessageType(byte(me.Reboot) | me.AK)
+	GetNextRequestType                = MessageType(byte(me.GetNext) | me.AR)
+	GetNextResponseType               = MessageType(byte(me.GetNext) | me.AK)
+	GetCurrentDataRequestType         = MessageType(byte(me.GetCurrentData) | me.AR)
+	GetCurrentDataResponseType        = MessageType(byte(me.GetCurrentData) | me.AK)
+	SetTableRequestType               = MessageType(byte(me.SetTable) | me.AR)
+	SetTableResponseType              = MessageType(byte(me.SetTable) | me.AK)
+	// Autonomous ONU messages
+	AlarmNotificationType    = MessageType(byte(me.AlarmNotification))
+	AttributeValueChangeType = MessageType(byte(me.AttributeValueChange))
+	TestResultType           = MessageType(byte(me.TestResult))
+)
+
+func (mt MessageType) String() string {
+	switch mt {
+	default:
+		return "Unknown"
+
+	case CreateRequestType:
+		return "Create Request"
+	case CreateResponseType:
+		return "Create Response"
+	case DeleteRequestType:
+		return "Delete Request"
+	case DeleteResponseType:
+		return "Delete Response"
+	case SetRequestType:
+		return "Set Request"
+	case SetResponseType:
+		return "Set Response"
+	case GetRequestType:
+		return "Get Request"
+	case GetResponseType:
+		return "Get Response"
+	case GetAllAlarmsRequestType:
+		return "Get All Alarms Request"
+	case GetAllAlarmsResponseType:
+		return "Get All Alarms Response"
+	case GetAllAlarmsNextRequestType:
+		return "Get All Alarms Next Request"
+	case GetAllAlarmsNextResponseType:
+		return "Get All Alarms Next Response"
+	case MibUploadRequestType:
+		return "MIB Upload Request"
+	case MibUploadResponseType:
+		return "MIB Upload Response"
+	case MibUploadNextRequestType:
+		return "MIB Upload Next Request"
+	case MibUploadNextResponseType:
+		return "MIB Upload Next Response"
+	case MibResetRequestType:
+		return "MIB Reset Request"
+	case MibResetResponseType:
+		return "MIB Reset Response"
+	case TestRequestType:
+		return "Test Request"
+	case TestResponseType:
+		return "Test Response"
+	case StartSoftwareDownloadRequestType:
+		return "Start Software Download Request"
+	case StartSoftwareDownloadResponseType:
+		return "Start Software Download Response"
+	case DownloadSectionRequestType:
+		return "Download Section Request"
+	case DownloadSectionResponseType:
+		return "Download Section Response"
+	case EndSoftwareDownloadRequestType:
+		return "End Software Download Request"
+	case EndSoftwareDownloadResponseType:
+		return "End Software Download Response"
+	case ActivateSoftwareRequestType:
+		return "Activate Software Request"
+	case ActivateSoftwareResponseType:
+		return "Activate Software Response"
+	case CommitSoftwareRequestType:
+		return "Commit Software Request"
+	case CommitSoftwareResponseType:
+		return "Commit Software Response"
+	case SynchronizeTimeRequestType:
+		return "Synchronize Time Request"
+	case SynchronizeTimeResponseType:
+		return "Synchronize Time Response"
+	case RebootRequestType:
+		return "Reboot Request"
+	case RebootResponseType:
+		return "Reboot Response"
+	case GetNextRequestType:
+		return "Get Next Request"
+	case GetNextResponseType:
+		return "Get Next Response"
+	case GetCurrentDataRequestType:
+		return "Get Current Data Request"
+	case GetCurrentDataResponseType:
+		return "Get Current Data Response"
+	case SetTableRequestType:
+		return "Set Table Request"
+	case SetTableResponseType:
+		return "Set Table Response"
+	case AlarmNotificationType:
+		return "Alarm Notification"
+	case AttributeValueChangeType:
+		return "Attribute Value Change"
+	case TestResultType:
+		return "Test Result"
+	}
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CreateRequest
+type CreateRequest struct {
+	MeBasePacket
+	Attributes me.AttributeValueMap
+}
+
+func (omci *CreateRequest) String() string {
+	return fmt.Sprintf("%v, attributes: %v", omci.MeBasePacket.String(), omci.Attributes)
+}
+
+// DecodeFromBytes decodes the given bytes of a Create Request into this layer
+func (omci *CreateRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	// Create attribute mask for all set-by-create entries
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Create
+	if !me.SupportsMsgType(meDefinition, me.Create) {
+		return me.NewProcessingError("managed entity does not support Create Message-Type")
+	}
+	var sbcMask uint16
+	for index, attr := range meDefinition.GetAttributeDefinitions() {
+		if me.SupportsAttributeAccess(attr, me.SetByCreate) {
+			if index == 0 {
+				continue // Skip Entity ID
+			}
+			sbcMask |= attr.Mask
+		}
+	}
+	// Attribute decode
+	omci.Attributes, err = meDefinition.DecodeAttributes(sbcMask, data[4:], p, byte(CreateRequestType))
+	if err != nil {
+		return err
+	}
+	if eidDef, eidDefOK := meDefinition.GetAttributeDefinitions()[0]; eidDefOK {
+		omci.Attributes[eidDef.GetName()] = omci.EntityInstance
+		return nil
+	}
+	panic("All Managed Entities have an EntityID attribute")
+}
+
+func decodeCreateRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &CreateRequest{}
+	omci.MsgLayerType = LayerTypeCreateRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Create Request Message
+func (omci *CreateRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// Create attribute mask of SetByCreate attributes that should be present in the provided
+	// attributes.
+	var sbcMask uint16
+	for index, attr := range meDefinition.GetAttributeDefinitions() {
+		if me.SupportsAttributeAccess(attr, me.SetByCreate) {
+			if index == 0 {
+				continue // Skip Entity ID
+			}
+			sbcMask |= attr.Mask
+		}
+	}
+	// Attribute serialization
+	// TODO: Only Baseline supported at this time
+	bytesAvailable := MaxBaselineLength - 8 - 8
+	err, _ = meDefinition.SerializeAttributes(omci.Attributes, sbcMask, b, byte(CreateRequestType), bytesAvailable, false)
+	return err
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CreateResponse
+type CreateResponse struct {
+	MeBasePacket
+	Result                 me.Results
+	AttributeExecutionMask uint16 // Used when Result == ParameterError
+}
+
+func (omci *CreateResponse) String() string {
+	return fmt.Sprintf("%v, Result: %d (%v), Mask: %#x",
+		omci.MeBasePacket.String(), omci.Result, omci.Result, omci.AttributeExecutionMask)
+}
+
+// DecodeFromBytes decodes the given bytes of a Create Response into this layer
+func (omci *CreateResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Create
+	if !me.SupportsMsgType(entity, me.Create) {
+		return me.NewProcessingError("managed entity does not support the Create Message-Type")
+	}
+	omci.Result = me.Results(data[4])
+	if omci.Result == me.ParameterError {
+		omci.AttributeExecutionMask = binary.BigEndian.Uint16(data[5:])
+		// TODO: validation that attributes set in mask are SetByCreate would be good here
+	}
+	return nil
+}
+
+func decodeCreateResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &CreateResponse{}
+	omci.MsgLayerType = LayerTypeCreateResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Create Response message
+func (omci *CreateResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Create
+	if !me.SupportsMsgType(entity, me.Create) {
+		return me.NewProcessingError("managed entity does not support the Create Message-Type")
+	}
+	bytes, err := b.AppendBytes(3)
+	if err != nil {
+		return err
+	}
+	bytes[0] = byte(omci.Result)
+	if omci.Result == me.ParameterError {
+		// TODO: validation that attributes set in mask are SetByCreate would be good here
+		binary.BigEndian.PutUint16(bytes[1:], omci.AttributeExecutionMask)
+	} else {
+		binary.BigEndian.PutUint16(bytes[1:], 0)
+	}
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// DeleteRequest
+type DeleteRequest struct {
+	MeBasePacket
+}
+
+func (omci *DeleteRequest) String() string {
+	return fmt.Sprintf("%v", omci.MeBasePacket.String())
+}
+
+// DecodeFromBytes decodes the given bytes of a Delete Request into this layer
+func (omci *DeleteRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Delete
+	if !me.SupportsMsgType(entity, me.Delete) {
+		return me.NewProcessingError("managed entity does not support the Delete Message-Type")
+	}
+	return nil
+}
+
+func decodeDeleteRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &DeleteRequest{}
+	omci.MsgLayerType = LayerTypeDeleteRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Delete Request message
+func (omci *DeleteRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Delete
+	if !me.SupportsMsgType(entity, me.Delete) {
+		return me.NewProcessingError("managed entity does not support the Delete Message-Type")
+	}
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// DeleteResponse
+type DeleteResponse struct {
+	MeBasePacket
+	Result me.Results
+}
+
+func (omci *DeleteResponse) String() string {
+	return fmt.Sprintf("%v, Result: %d (%v)",
+		omci.MeBasePacket.String(), omci.Result, omci.Result)
+}
+
+// DecodeFromBytes decodes the given bytes of a Delete Response into this layer
+func (omci *DeleteResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Delete
+	if !me.SupportsMsgType(entity, me.Delete) {
+		return me.NewProcessingError("managed entity does not support the Delete Message-Type")
+	}
+	omci.Result = me.Results(data[4])
+	return nil
+}
+
+func decodeDeleteResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &DeleteResponse{}
+	omci.MsgLayerType = LayerTypeDeleteResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Delete Response message
+func (omci *DeleteResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Delete
+	if !me.SupportsMsgType(entity, me.Delete) {
+		return me.NewProcessingError("managed entity does not support the Delete Message-Type")
+	}
+	bytes, err := b.AppendBytes(1)
+	if err != nil {
+		return err
+	}
+	bytes[0] = byte(omci.Result)
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// SetRequest
+type SetRequest struct {
+	MeBasePacket
+	AttributeMask uint16
+	Attributes    me.AttributeValueMap
+}
+
+func (omci *SetRequest) String() string {
+	return fmt.Sprintf("%v, Mask: %#x, attributes: %v",
+		omci.MeBasePacket.String(), omci.AttributeMask, omci.Attributes)
+}
+
+// DecodeFromBytes decodes the given bytes of a Set Request into this layer
+func (omci *SetRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Set
+	if !me.SupportsMsgType(meDefinition, me.Set) {
+		return me.NewProcessingError("managed entity does not support Set Message-Type")
+	}
+	omci.AttributeMask = binary.BigEndian.Uint16(data[4:6])
+
+	// Attribute decode
+	omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask, data[6:], p, byte(SetRequestType))
+	if err != nil {
+		return err
+	}
+	// Validate all attributes support write
+	for attrName := range omci.Attributes {
+		attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
+		if err != nil {
+			return err
+		}
+		if attr.Index != 0 && !me.SupportsAttributeAccess(*attr, me.Write) {
+			msg := fmt.Sprintf("attribute '%v' does not support write access", attrName)
+			return me.NewProcessingError(msg)
+		}
+	}
+	if eidDef, eidDefOK := meDefinition.GetAttributeDefinitions()[0]; eidDefOK {
+		omci.Attributes[eidDef.GetName()] = omci.EntityInstance
+		return nil
+	}
+	panic("All Managed Entities have an EntityID attribute")
+}
+
+func decodeSetRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &SetRequest{}
+	omci.MsgLayerType = LayerTypeSetRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Set Request message
+func (omci *SetRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Set
+	if !me.SupportsMsgType(meDefinition, me.Set) {
+		return me.NewProcessingError("managed entity does not support Set Message-Type")
+	}
+	// Validate all attributes support write
+	for attrName := range omci.Attributes {
+		attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
+		if err != nil {
+			return err
+		}
+		// Do not test for write of Entity ID in the attribute list
+		if attr.Index != 0 && !me.SupportsAttributeAccess(*attr, me.Write) {
+			// TODO: Check ITU spec to see if this should be listed as a failed
+			//       attribute and not a processing error.
+			msg := fmt.Sprintf("attribute '%v' does not support write access", attrName)
+			return me.NewProcessingError(msg)
+		}
+	}
+	bytes, err := b.AppendBytes(2)
+	if err != nil {
+		return err
+	}
+	binary.BigEndian.PutUint16(bytes, omci.AttributeMask)
+
+	// Attribute serialization
+	// TODO: Only Baseline supported at this time
+	bytesAvailable := MaxBaselineLength - 10 - 8
+
+	err, _ = meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask, b,
+		byte(SetRequestType), bytesAvailable, false)
+	return err
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// SetResponse
+type SetResponse struct {
+	MeBasePacket
+	Result                   me.Results
+	UnsupportedAttributeMask uint16
+	FailedAttributeMask      uint16
+}
+
+func (omci *SetResponse) String() string {
+	return fmt.Sprintf("%v, Result: %d (%v), Unsupported Mask: %#x, Failed Mask: %#x",
+		omci.MeBasePacket.String(), omci.Result, omci.Result, omci.UnsupportedAttributeMask,
+		omci.FailedAttributeMask)
+}
+
+// DecodeFromBytes decodes the given bytes of a Set Response into this layer
+func (omci *SetResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Set
+	if !me.SupportsMsgType(entity, me.Set) {
+		return me.NewProcessingError("managed entity does not support the Delete Message-Type")
+	}
+	omci.Result = me.Results(data[4])
+
+	if omci.Result == me.AttributeFailure {
+		omci.UnsupportedAttributeMask = binary.BigEndian.Uint16(data[5:7])
+		omci.FailedAttributeMask = binary.BigEndian.Uint16(data[7:9])
+	}
+	return nil
+}
+
+func decodeSetResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &SetResponse{}
+	omci.MsgLayerType = LayerTypeSetResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Set Response message
+func (omci *SetResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Set
+	if !me.SupportsMsgType(entity, me.Set) {
+		return me.NewProcessingError("managed entity does not support the Set Message-Type")
+	}
+	bytes, err := b.AppendBytes(5)
+	if err != nil {
+		return err
+	}
+	bytes[0] = byte(omci.Result)
+	binary.BigEndian.PutUint16(bytes[1:3], omci.UnsupportedAttributeMask)
+	binary.BigEndian.PutUint16(bytes[3:5], omci.FailedAttributeMask)
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// GetRequest
+type GetRequest struct {
+	MeBasePacket
+	AttributeMask uint16
+}
+
+func (omci *GetRequest) String() string {
+	return fmt.Sprintf("%v, Mask: %#x",
+		omci.MeBasePacket.String(), omci.AttributeMask)
+}
+
+// DecodeFromBytes decodes the given bytes of a Get Request into this layer
+func (omci *GetRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Get
+	if !me.SupportsMsgType(meDefinition, me.Get) {
+		return me.NewProcessingError("managed entity does not support Get Message-Type")
+	}
+	omci.AttributeMask = binary.BigEndian.Uint16(data[4:6])
+	return nil
+}
+
+func decodeGetRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetRequest{}
+	omci.MsgLayerType = LayerTypeGetRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Get Request message
+func (omci *GetRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Set
+	if !me.SupportsMsgType(meDefinition, me.Get) {
+		return me.NewProcessingError("managed entity does not support Get Message-Type")
+	}
+	bytes, err := b.AppendBytes(2)
+	if err != nil {
+		return err
+	}
+	binary.BigEndian.PutUint16(bytes, omci.AttributeMask)
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// GetResponse
+type GetResponse struct {
+	MeBasePacket
+	Result                   me.Results
+	AttributeMask            uint16
+	Attributes               me.AttributeValueMap
+	UnsupportedAttributeMask uint16
+	FailedAttributeMask      uint16
+}
+
+func (omci *GetResponse) String() string {
+	return fmt.Sprintf("%v, Result: %d (%v), Mask: %#x, Unsupported: %#x, Failed: %#x, attributes: %v",
+		omci.MeBasePacket.String(), omci.Result, omci.Result, omci.AttributeMask,
+		omci.UnsupportedAttributeMask, omci.FailedAttributeMask, omci.Attributes)
+}
+
+// DecodeFromBytes decodes the given bytes of a Get Response into this layer
+func (omci *GetResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Get
+	if !me.SupportsMsgType(meDefinition, me.Get) {
+		return me.NewProcessingError("managed entity does not support Get Message-Type")
+	}
+	omci.Result = me.Results(data[4])
+	omci.AttributeMask = binary.BigEndian.Uint16(data[5:7])
+
+	// Attribute decode. Note that the ITU-T G.988 specification states that the
+	//                   Unsupported and Failed attribute masks are always present
+	//                   but only valid if the status code== 9.  However some XGS
+	//                   ONUs (T&W and Alpha, perhaps more) will use these last 4
+	//                   octets for data if the status code == 0.  So accommodate
+	//                   this behaviour in favor of greater interoperability.
+	lastOctet := 36
+	if omci.Result == me.AttributeFailure {
+		lastOctet = 32
+	}
+	omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask, data[7:lastOctet], p, byte(GetResponseType))
+	if err != nil {
+		return err
+	}
+	// If Attribute failed or Unknown, decode optional attribute mask
+	if omci.Result == me.AttributeFailure {
+		omci.UnsupportedAttributeMask = binary.BigEndian.Uint16(data[32:34])
+		omci.FailedAttributeMask = binary.BigEndian.Uint16(data[34:36])
+	}
+	// Validate all attributes support read
+	for attrName := range omci.Attributes {
+		attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
+		if err != nil {
+			return err
+		}
+		if attr.Index != 0 && !me.SupportsAttributeAccess(*attr, me.Read) {
+			msg := fmt.Sprintf("attribute '%v' does not support read access", attrName)
+			return me.NewProcessingError(msg)
+		}
+	}
+	if eidDef, eidDefOK := meDefinition.GetAttributeDefinitions()[0]; eidDefOK {
+		omci.Attributes[eidDef.GetName()] = omci.EntityInstance
+		return nil
+	}
+	panic("All Managed Entities have an EntityID attribute")
+}
+
+func decodeGetResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetResponse{}
+	omci.MsgLayerType = LayerTypeGetResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Get Response message
+func (omci *GetResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	if err := omci.MeBasePacket.SerializeTo(b); err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Get
+	if !me.SupportsMsgType(meDefinition, me.Get) {
+		return me.NewProcessingError("managed entity does not support the Get Message-Type")
+	}
+	bytes, err := b.AppendBytes(3)
+	if err != nil {
+		return err
+	}
+	bytes[0] = byte(omci.Result)
+	binary.BigEndian.PutUint16(bytes[1:3], omci.AttributeMask)
+
+	// Validate all attributes support read
+	for attrName := range omci.Attributes {
+		attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
+		if err != nil {
+			return err
+		}
+		if attr.Index != 0 && !me.SupportsAttributeAccess(*attr, me.Read) {
+			msg := fmt.Sprintf("attribute '%v' does not support read access", attrName)
+			return me.NewProcessingError(msg)
+		}
+	}
+	// Attribute serialization
+	switch omci.Result {
+	default:
+		break
+
+	case me.Success, me.AttributeFailure:
+		// TODO: Baseline only supported at this time)
+		available := MaxBaselineLength - 11 - 4 - 8
+
+		// Serialize to temporary buffer if we may need to reset values due to
+		// recoverable truncation errors
+		origBuffer := b
+		b := gopacket.NewSerializeBuffer()
+
+		err, failedMask := meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask, b, byte(GetResponseType),
+			available, opts.FixLengths)
+
+		if err == nil && failedMask != 0 && opts.FixLengths {
+			// Not all attributes would fit
+			omci.FailedAttributeMask |= failedMask
+			omci.AttributeMask &= ^failedMask
+			omci.Result = me.AttributeFailure
+
+			// Adjust already recorded values
+			bytes[0] = byte(omci.Result)
+			binary.BigEndian.PutUint16(bytes[1:3], omci.AttributeMask)
+		} else if err != nil {
+			return err
+		}
+		// Copy over attributes to the original serialization buffer
+		newSpace, err := origBuffer.AppendBytes(len(b.Bytes()))
+		if err != nil {
+			return err
+		}
+		copy(newSpace, b.Bytes())
+		b = origBuffer
+
+		// Calculate space left. Max  - msgType header - OMCI trailer - spacedUsedSoFar
+		bytesLeft := MaxBaselineLength - 4 - 8 - len(b.Bytes())
+
+		remainingBytes, err := b.AppendBytes(bytesLeft + 4)
+		if err != nil {
+			return me.NewMessageTruncatedError(err.Error())
+		}
+		copy(remainingBytes, lotsOfZeros[:])
+
+		if omci.Result == me.AttributeFailure {
+			binary.BigEndian.PutUint16(remainingBytes[bytesLeft-4:bytesLeft-2], omci.UnsupportedAttributeMask)
+			binary.BigEndian.PutUint16(remainingBytes[bytesLeft-2:bytesLeft], omci.FailedAttributeMask)
+		}
+	}
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// GetAllAlarms
+type GetAllAlarmsRequest struct {
+	MeBasePacket
+	AlarmRetrievalMode byte
+}
+
+func (omci *GetAllAlarmsRequest) String() string {
+	return fmt.Sprintf("%v, Retrieval Mode: %v",
+		omci.MeBasePacket.String(), omci.AlarmRetrievalMode)
+}
+
+// DecodeFromBytes decodes the given bytes of a Get All Alarms Request into this layer
+func (omci *GetAllAlarmsRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Get All Alarms
+	if !me.SupportsMsgType(meDefinition, me.GetAllAlarms) {
+		return me.NewProcessingError("managed entity does not support Get All Alarms Message-Type")
+	}
+	// Entity Class are always ONU DATA (2) and Entity Instance of 0
+	if omci.EntityClass != me.OnuDataClassID {
+		msg := fmt.Sprintf("invalid Entity Class for Get All Alarms request: %v",
+			omci.EntityClass)
+		return me.NewProcessingError(msg)
+	}
+	if omci.EntityInstance != 0 {
+		msg := fmt.Sprintf("invalid Entity Instance for Get All Alarms request: %v",
+			omci.EntityInstance)
+		return me.NewUnknownInstanceError(msg)
+	}
+	omci.AlarmRetrievalMode = data[4]
+	if omci.AlarmRetrievalMode > 1 {
+		msg := fmt.Sprintf("invalid Alarm Retrieval Mode for Get All Alarms request: %v, must be 0..1",
+			omci.AlarmRetrievalMode)
+		return errors.New(msg)
+	}
+	return nil
+}
+
+func decodeGetAllAlarmsRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetAllAlarmsRequest{}
+	omci.MsgLayerType = LayerTypeGetAllAlarmsRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Get All Alarms Request message
+func (omci *GetAllAlarmsRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Get All Alarms
+	if !me.SupportsMsgType(entity, me.GetAllAlarms) {
+		return me.NewProcessingError("managed entity does not support the Get All Alarms Message-Type")
+	}
+	bytes, err := b.AppendBytes(1)
+	if err != nil {
+		return err
+	}
+	bytes[0] = omci.AlarmRetrievalMode
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// GetAllAlarms
+type GetAllAlarmsResponse struct {
+	MeBasePacket
+	NumberOfCommands uint16
+}
+
+func (omci *GetAllAlarmsResponse) String() string {
+	return fmt.Sprintf("%v, NumberOfCommands: %d",
+		omci.MeBasePacket.String(), omci.NumberOfCommands)
+}
+
+// DecodeFromBytes decodes the given bytes of a Get All Alarms Response into this layer
+func (omci *GetAllAlarmsResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Get All Alarms
+	if !me.SupportsMsgType(meDefinition, me.GetAllAlarms) {
+		return me.NewProcessingError("managed entity does not support Get All Alarms Message-Type")
+	}
+	// Entity Class are always ONU DATA (2) and Entity Instance of 0
+	if omci.EntityClass != me.OnuDataClassID {
+		msg := fmt.Sprintf("invalid Entity Class for Get All Alarms response: %v",
+			omci.EntityClass)
+		return me.NewProcessingError(msg)
+	}
+	if omci.EntityInstance != 0 {
+		msg := fmt.Sprintf("invalid Entity Instance for Get All Alarms response: %v",
+			omci.EntityInstance)
+		return me.NewUnknownInstanceError(msg)
+	}
+	omci.NumberOfCommands = binary.BigEndian.Uint16(data[4:6])
+	return nil
+}
+
+func decodeGetAllAlarmsResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetAllAlarmsResponse{}
+	omci.MsgLayerType = LayerTypeGetAllAlarmsResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Get All Alarms Response message
+func (omci *GetAllAlarmsResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Get All Alarms
+	if !me.SupportsMsgType(entity, me.GetAllAlarms) {
+		return me.NewProcessingError("managed entity does not support the Get All Alarms Message-Type")
+	}
+	bytes, err := b.AppendBytes(2)
+	if err != nil {
+		return err
+	}
+	binary.BigEndian.PutUint16(bytes[0:2], omci.NumberOfCommands)
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// GetAllAlarms
+type GetAllAlarmsNextRequest struct {
+	MeBasePacket
+	CommandSequenceNumber uint16
+}
+
+func (omci *GetAllAlarmsNextRequest) String() string {
+	return fmt.Sprintf("%v, Sequence Number: %d",
+		omci.MeBasePacket.String(), omci.CommandSequenceNumber)
+}
+
+// DecodeFromBytes decodes the given bytes of a Get All Alarms Next Request into this layer
+func (omci *GetAllAlarmsNextRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Get All Alarms
+	if !me.SupportsMsgType(meDefinition, me.GetAllAlarmsNext) {
+		return me.NewProcessingError("managed entity does not support Get All Alarms Next Message-Type")
+	}
+	// Entity Class are always ONU DATA (2) and Entity Instance of 0
+	if omci.EntityClass != me.OnuDataClassID {
+		msg := fmt.Sprintf("invalid Entity Class for Get All Alarms Next request: %v",
+			omci.EntityClass)
+		return me.NewProcessingError(msg)
+	}
+	if omci.EntityInstance != 0 {
+		msg := fmt.Sprintf("invalid Entity Instance for Get All Alarms Next request: %v",
+			omci.EntityInstance)
+		return me.NewUnknownInstanceError(msg)
+	}
+	omci.CommandSequenceNumber = binary.BigEndian.Uint16(data[4:6])
+	return nil
+}
+
+func decodeGetAllAlarmsNextRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetAllAlarmsNextRequest{}
+	omci.MsgLayerType = LayerTypeGetAllAlarmsNextRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Get All Alarms Next Request message
+func (omci *GetAllAlarmsNextRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Get All Alarms Next
+	if !me.SupportsMsgType(entity, me.GetAllAlarmsNext) {
+		return me.NewProcessingError("managed entity does not support the Get All Alarms Next Message-Type")
+	}
+	bytes, err := b.AppendBytes(2)
+	if err != nil {
+		return err
+	}
+	binary.BigEndian.PutUint16(bytes, omci.CommandSequenceNumber)
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// GetAllAlarms
+type GetAllAlarmsNextResponse struct {
+	MeBasePacket
+	AlarmEntityClass    me.ClassID
+	AlarmEntityInstance uint16
+	AlarmBitMap         [28]byte // 224 bits
+}
+
+func (omci *GetAllAlarmsNextResponse) String() string {
+	return fmt.Sprintf("%v, CID: %v, EID: (%d/%#x), Bitmap: %v",
+		omci.MeBasePacket.String(), omci.AlarmEntityClass, omci.AlarmEntityInstance,
+		omci.AlarmEntityInstance, omci.AlarmBitMap)
+}
+
+// DecodeFromBytes decodes the given bytes of a Get All Alarms Next Response into this layer
+func (omci *GetAllAlarmsNextResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Get All Alarms Next
+	if !me.SupportsMsgType(meDefinition, me.GetAllAlarmsNext) {
+		return me.NewProcessingError("managed entity does not support Get All Alarms Next Message-Type")
+	}
+	// Entity Class are always ONU DATA (2) and Entity Instance of 0
+	if omci.EntityClass != me.OnuDataClassID {
+		msg := fmt.Sprintf("invalid Entity Class for Get All Alarms Next response: %v",
+			omci.EntityClass)
+		return me.NewProcessingError(msg)
+	}
+	if omci.EntityInstance != 0 {
+		msg := fmt.Sprintf("invalid Entity Instance for Get All Alarms Next response: %v",
+			omci.EntityInstance)
+		return me.NewUnknownInstanceError(msg)
+	}
+	omci.AlarmEntityClass = me.ClassID(binary.BigEndian.Uint16(data[4:6]))
+	omci.AlarmEntityInstance = binary.BigEndian.Uint16(data[6:8])
+
+	copy(omci.AlarmBitMap[:], data[8:36])
+	return nil
+}
+
+func decodeGetAllAlarmsNextResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetAllAlarmsNextResponse{}
+	omci.MsgLayerType = LayerTypeGetAllAlarmsNextResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Get All Alarms Next Response message
+func (omci *GetAllAlarmsNextResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Get All Alarms Next
+	if !me.SupportsMsgType(entity, me.GetAllAlarmsNext) {
+		return me.NewProcessingError("managed entity does not support the Get All Alarms Next Message-Type")
+	}
+	bytes, err := b.AppendBytes(2 + 2 + 28)
+	if err != nil {
+		return err
+	}
+	binary.BigEndian.PutUint16(bytes[0:], uint16(omci.AlarmEntityClass))
+	binary.BigEndian.PutUint16(bytes[2:], omci.AlarmEntityInstance)
+	copy(bytes[4:], omci.AlarmBitMap[:])
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// MibUploadRequest
+type MibUploadRequest struct {
+	MeBasePacket
+}
+
+func (omci *MibUploadRequest) String() string {
+	return fmt.Sprintf("%v", omci.MeBasePacket.String())
+}
+
+// DecodeFromBytes decodes the given bytes of a MIB Upload Request into this layer
+func (omci *MibUploadRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support MIB Upload
+	if !me.SupportsMsgType(meDefinition, me.MibUpload) {
+		return me.NewProcessingError("managed entity does not support MIB Upload Message-Type")
+	}
+	// Entity Class are always ONU DATA (2) and Entity Instance of 0
+	if omci.EntityClass != me.OnuDataClassID {
+		msg := fmt.Sprintf("invalid Entity Class for  MIB Upload request: %v",
+			omci.EntityClass)
+		return me.NewProcessingError(msg)
+	}
+	if omci.EntityInstance != 0 {
+		msg := fmt.Sprintf("invalid Entity Instance for MIB Upload request: %v",
+			omci.EntityInstance)
+		return me.NewUnknownInstanceError(msg)
+	}
+	return nil
+}
+
+func decodeMibUploadRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &MibUploadRequest{}
+	omci.MsgLayerType = LayerTypeMibUploadRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an MIB Upload Request message
+func (omci *MibUploadRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Get
+	if !me.SupportsMsgType(meDefinition, me.MibUpload) {
+		return me.NewProcessingError("managed entity does not support the MIB Upload Message-Type")
+	}
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// MibUploadResponse
+type MibUploadResponse struct {
+	MeBasePacket
+	NumberOfCommands uint16
+}
+
+func (omci *MibUploadResponse) String() string {
+	return fmt.Sprintf("%v, NumberOfCommands: %#v",
+		omci.MeBasePacket.String(), omci.NumberOfCommands)
+}
+
+// DecodeFromBytes decodes the given bytes of a MIB Upload Response into this layer
+func (omci *MibUploadResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support MIB Upload
+	if !me.SupportsMsgType(meDefinition, me.MibUpload) {
+		return me.NewProcessingError("managed entity does not support MIB Upload Message-Type")
+	}
+	// Entity Class are always ONU DATA (2) and Entity Instance of 0
+	if omci.EntityClass != me.OnuDataClassID {
+		msg := fmt.Sprintf("invalid Entity Class for  MIB Upload response: %v",
+			omci.EntityClass)
+		return me.NewProcessingError(msg)
+	}
+	if omci.EntityInstance != 0 {
+		msg := fmt.Sprintf("invalid Entity Instance for MIB Upload response: %v",
+			omci.EntityInstance)
+		return me.NewUnknownInstanceError(msg)
+	}
+	omci.NumberOfCommands = binary.BigEndian.Uint16(data[4:6])
+	return nil
+}
+
+func decodeMibUploadResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &MibUploadResponse{}
+	omci.MsgLayerType = LayerTypeMibUploadResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an MIB Upload Response message
+func (omci *MibUploadResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support MIB Upload
+	if !me.SupportsMsgType(entity, me.MibUpload) {
+		return me.NewProcessingError("managed entity does not support the MIB Upload Message-Type")
+	}
+	bytes, err := b.AppendBytes(2)
+	if err != nil {
+		return err
+	}
+	binary.BigEndian.PutUint16(bytes[0:2], omci.NumberOfCommands)
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type MibUploadNextRequest struct {
+	MeBasePacket
+	CommandSequenceNumber uint16
+}
+
+func (omci *MibUploadNextRequest) String() string {
+	return fmt.Sprintf("%v, SequenceNumberCountOrSize: %v",
+		omci.MeBasePacket.String(), omci.CommandSequenceNumber)
+}
+
+// DecodeFromBytes decodes the given bytes of a MIB Upload Next Request into this layer
+func (omci *MibUploadNextRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Get All Alarms
+	if !me.SupportsMsgType(meDefinition, me.MibUploadNext) {
+		return me.NewProcessingError("managed entity does not support MIB Upload Next Message-Type")
+	}
+	// Entity Class are always ONU DATA (2) and Entity Instance of 0
+	if omci.EntityClass != me.OnuDataClassID {
+		msg := fmt.Sprintf("invalid Entity Class for  MIB Upload Next request: %v",
+			omci.EntityClass)
+		return me.NewProcessingError(msg)
+	}
+	if omci.EntityInstance != 0 {
+		msg := fmt.Sprintf("invalid Entity Instance for MIB Upload Next request: %v",
+			omci.EntityInstance)
+		return me.NewUnknownInstanceError(msg)
+	}
+	omci.CommandSequenceNumber = binary.BigEndian.Uint16(data[4:6])
+	return nil
+}
+
+func decodeMibUploadNextRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &MibUploadNextRequest{}
+	omci.MsgLayerType = LayerTypeMibUploadNextRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an MIB Upload Next Request message
+func (omci *MibUploadNextRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support MIB upload
+	if !me.SupportsMsgType(entity, me.MibUploadNext) {
+		return me.NewProcessingError("managed entity does not support the MIB Upload Next Message-Type")
+	}
+	bytes, err := b.AppendBytes(2)
+	if err != nil {
+		return err
+	}
+	binary.BigEndian.PutUint16(bytes[0:2], omci.CommandSequenceNumber)
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type MibUploadNextResponse struct {
+	MeBasePacket
+	ReportedME me.ManagedEntity
+}
+
+func (omci *MibUploadNextResponse) String() string {
+	return fmt.Sprintf("%v, ReportedME: [%v]",
+		omci.MeBasePacket.String(), omci.ReportedME.String())
+}
+
+// DecodeFromBytes decodes the given bytes of a MIB Upload Next Response into this layer
+func (omci *MibUploadNextResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support MibUploadNext
+	if !me.SupportsMsgType(meDefinition, me.MibUploadNext) {
+		return me.NewProcessingError("managed entity does not support MIB Upload Next Message-Type")
+	}
+	// Entity Class are always ONU DATA (2) and Entity Instance of 0
+	if omci.EntityClass != me.OnuDataClassID {
+		msg := fmt.Sprintf("invalid Entity Class for  MIB Upload Next response: %v",
+			omci.EntityClass)
+		return me.NewProcessingError(msg)
+	}
+	if omci.EntityInstance != 0 {
+		msg := fmt.Sprintf("invalid Entity Instance for MIB Upload Next response: %v",
+			omci.EntityInstance)
+		return me.NewUnknownInstanceError(msg)
+	}
+	// Decode reported ME.  If an out-of-range sequence number was sent, this will
+	// contain an ME with class ID and entity ID of zero and you should get an
+	// error of "managed entity definition not found" returned.
+	return omci.ReportedME.DecodeFromBytes(data[4:], p, byte(MibUploadNextResponseType))
+}
+
+func decodeMibUploadNextResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &MibUploadNextResponse{}
+	omci.MsgLayerType = LayerTypeMibUploadNextResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an MIB Upload Next Response message
+func (omci *MibUploadNextResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support MIB Upload
+	if !me.SupportsMsgType(entity, me.MibUploadNext) {
+		return me.NewProcessingError("managed entity does not support the MIB Upload Next Message-Type")
+	}
+	// TODO: Only Baseline supported at this time
+	bytesAvailable := MaxBaselineLength - 8 - 8
+
+	return omci.ReportedME.SerializeTo(b, byte(MibUploadNextResponseType), bytesAvailable, opts)
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// MibResetRequest
+type MibResetRequest struct {
+	MeBasePacket
+}
+
+func (omci *MibResetRequest) String() string {
+	return fmt.Sprintf("%v", omci.MeBasePacket.String())
+}
+
+// DecodeFromBytes decodes the given bytes of a MIB Reset Request into this layer
+func (omci *MibResetRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support MIB reset
+	if !me.SupportsMsgType(meDefinition, me.MibReset) {
+		return me.NewProcessingError("managed entity does not support MIB Reset Message-Type")
+	}
+	// Entity Class are always ONU DATA (2) and Entity Instance of 0
+	if omci.EntityClass != me.OnuDataClassID {
+		msg := fmt.Sprintf("invalid Entity Class for MIB Reset request: %v",
+			omci.EntityClass)
+		return me.NewProcessingError(msg)
+	}
+	if omci.EntityInstance != 0 {
+		msg := fmt.Sprintf("invalid Entity Instance for MIB Reset request: %v",
+			omci.EntityInstance)
+		return me.NewUnknownInstanceError(msg)
+	}
+	return nil
+}
+
+func decodeMibResetRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &MibResetRequest{}
+	omci.MsgLayerType = LayerTypeMibResetRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an MIB Reset Request message
+func (omci *MibResetRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Add class ID and entity ID
+	return omci.MeBasePacket.SerializeTo(b)
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// MibResetResponse
+type MibResetResponse struct {
+	MeBasePacket
+	Result me.Results
+}
+
+func (omci *MibResetResponse) String() string {
+	return fmt.Sprintf("%v, Result: %d (%v)",
+		omci.MeBasePacket.String(), omci.Result, omci.Result)
+}
+
+// DecodeFromBytes decodes the given bytes of a MIB Reset Response into this layer
+func (omci *MibResetResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support MIB reset
+	if !me.SupportsMsgType(meDefinition, me.MibReset) {
+		return me.NewProcessingError("managed entity does not support MIB Reset Message-Type")
+	}
+	// MIB Reset Response Entity Class always ONU DATA (2) and
+	// Entity Instance of 0
+	if omci.EntityClass != me.OnuDataClassID {
+		return me.NewProcessingError("invalid Entity Class for MIB Reset Response")
+	}
+	if omci.EntityInstance != 0 {
+		return me.NewUnknownInstanceError("invalid Entity Instance for MIB Reset Response")
+	}
+	omci.Result = me.Results(data[4])
+	if omci.Result > me.DeviceBusy {
+		msg := fmt.Sprintf("invalid results code: %v, must be 0..8", omci.Result)
+		return errors.New(msg)
+	}
+	return nil
+}
+
+func decodeMibResetResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &MibResetResponse{}
+	omci.MsgLayerType = LayerTypeMibResetResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an MIB Reset Response message
+func (omci *MibResetResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Set
+	if !me.SupportsMsgType(entity, me.MibReset) {
+		return me.NewProcessingError("managed entity does not support the MIB Reset Message-Type")
+	}
+	bytes, err := b.AppendBytes(1)
+	if err != nil {
+		return err
+	}
+	bytes[0] = byte(omci.Result)
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// AlarmNotificationMsg
+const AlarmBitmapSize = 224
+
+type AlarmNotificationMsg struct {
+	MeBasePacket
+	AlarmBitmap         [AlarmBitmapSize / 8]byte
+	zeroPadding         [3]byte
+	AlarmSequenceNumber byte
+}
+
+func (omci *AlarmNotificationMsg) String() string {
+	return fmt.Sprintf("%v, Sequence Number: %d, Alarm Bitmap: %v",
+		omci.MeBasePacket.String(), omci.AlarmSequenceNumber, omci.AlarmBitmap)
+}
+
+func (omci *AlarmNotificationMsg) IsAlarmActive(alarmNumber uint8) (bool, error) {
+	if alarmNumber >= AlarmBitmapSize {
+		msg := fmt.Sprintf("invalid alarm number: %v, must be 0..224", alarmNumber)
+		return false, errors.New(msg)
+	}
+	octet := alarmNumber / 8
+	bit := 7 - (alarmNumber % 8)
+	return omci.AlarmBitmap[octet]>>bit == 1, nil
+}
+
+func (omci *AlarmNotificationMsg) IsAlarmClear(alarmNumber uint8) (bool, error) {
+	if alarmNumber >= AlarmBitmapSize {
+		msg := fmt.Sprintf("invalid alarm number: %v, must be 0..224", alarmNumber)
+		return false, errors.New(msg)
+	}
+	octet := alarmNumber / 8
+	bit := 7 - (alarmNumber % 8)
+	return omci.AlarmBitmap[octet]>>bit == 0, nil
+}
+
+func (omci *AlarmNotificationMsg) ActivateAlarm(alarmNumber uint8) error {
+	if alarmNumber >= AlarmBitmapSize {
+		msg := fmt.Sprintf("invalid alarm number: %v, must be 0..224", alarmNumber)
+		return errors.New(msg)
+	}
+	octet := alarmNumber / 8
+	bit := 7 - (alarmNumber % 8)
+	omci.AlarmBitmap[octet] |= 1 << bit
+	return nil
+}
+
+func (omci *AlarmNotificationMsg) ClearAlarm(alarmNumber uint8) error {
+	if alarmNumber >= AlarmBitmapSize {
+		msg := fmt.Sprintf("invalid alarm number: %v, must be 0..224", alarmNumber)
+		return errors.New(msg)
+	}
+	octet := alarmNumber / 8
+	bit := 7 - (alarmNumber % 8)
+	omci.AlarmBitmap[octet] &= ^(1 << bit)
+	return nil
+}
+
+// DecodeFromBytes decodes the given bytes of an Alarm Notification into this layer
+func (omci *AlarmNotificationMsg) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	//var meDefinition me.IManagedEntityDefinition
+	//meDefinition, err = me.LoadManagedEntityDefinition(omci.EntityClass,
+	//	me.ParamData{EntityID: omci.EntityInstance})
+	//if err != nil {
+	//	return err
+	//}
+	// ME needs to support Alarms
+	// TODO: Add attribute to ME to specify that alarm is allowed
+	//if !me.SupportsMsgType(meDefinition, me.MibReset) {
+	//	return me.NewProcesssingError("managed entity does not support MIB Reset Message-Type")
+	//}
+	for index, octet := range data[4 : (AlarmBitmapSize/8)-4] {
+		omci.AlarmBitmap[index] = octet
+	}
+	padOffset := 4 + (AlarmBitmapSize / 8)
+	omci.zeroPadding[0] = data[padOffset]
+	omci.zeroPadding[1] = data[padOffset+1]
+	omci.zeroPadding[2] = data[padOffset+2]
+
+	omci.AlarmSequenceNumber = data[padOffset+3]
+	return nil
+}
+
+func decodeAlarmNotification(data []byte, p gopacket.PacketBuilder) error {
+	omci := &AlarmNotificationMsg{}
+	omci.MsgLayerType = LayerTypeAlarmNotification
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Alarm Notification message
+func (omci *AlarmNotificationMsg) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	//var meDefinition me.IManagedEntityDefinition
+	//meDefinition, err = me.LoadManagedEntityDefinition(omci.EntityClass,
+	//	me.ParamData{EntityID: omci.EntityInstance})
+	//if err != nil {
+	//	return err
+	//}
+	// ME needs to support Alarms
+	// TODO: Add attribute to ME to specify that alarm is allowed
+	//if !me.SupportsMsgType(meDefinition, me.MibReset) {
+	//	return me.NewProcessingError("managed entity does not support MIB Reset Message-Type")
+	//}
+	bytes, err := b.AppendBytes((AlarmBitmapSize / 8) + 3 + 1)
+	if err != nil {
+		return err
+	}
+	for index, octet := range omci.AlarmBitmap {
+		bytes[index] = octet
+	}
+	padOffset := AlarmBitmapSize / 8
+	bytes[padOffset] = 0
+	bytes[padOffset+1] = 0
+	bytes[padOffset+2] = 0
+	bytes[padOffset+3] = omci.AlarmSequenceNumber
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// AttributeValueChangeMsg
+type AttributeValueChangeMsg struct {
+	MeBasePacket
+	AttributeMask uint16
+	Attributes    me.AttributeValueMap
+}
+
+func (omci *AttributeValueChangeMsg) String() string {
+	return fmt.Sprintf("%v, Mask: %#x, attributes: %v",
+		omci.MeBasePacket.String(), omci.AttributeMask, omci.Attributes)
+}
+
+// DecodeFromBytes decodes the given bytes of an Attribute Value Change notification into this layer
+func (omci *AttributeValueChangeMsg) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	omci.AttributeMask = binary.BigEndian.Uint16(data[4:6])
+	// Attribute decode
+	omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask, data[6:40], p, byte(AttributeValueChangeType))
+	// TODO: Add support for attributes that can have an AVC associated with them and then add a check here
+	// Validate all attributes support AVC
+	//for attrName := range omci.attributes {
+	//	attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
+	//	if err != nil {
+	//		return err
+	//	}
+	//	if attr.Index != 0 && !me.SupportsAttributeAVC(attr) {
+	//		msg := fmt.Sprintf("attribute '%v' does not support AVC notifications", attrName)
+	//		return me.NewProcessingError(msg)
+	//	}
+	//}
+	return err
+}
+
+func decodeAttributeValueChange(data []byte, p gopacket.PacketBuilder) error {
+	omci := &AttributeValueChangeMsg{}
+	omci.MsgLayerType = LayerTypeAttributeValueChange
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Attribute Value Change Notification message
+func (omci *AttributeValueChangeMsg) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// TODO: Add support for attributes that can have an AVC associated with them and then add a check here
+	// Validate all attributes support AVC
+	//for attrName := range omci.attributes {
+	//	attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
+	//	if err != nil {
+	//		return err
+	//	}
+	//	if attr.Index != 0 && !me.SupportsAttributeAVC(attr) {
+	//		msg := fmt.Sprintf("attribute '%v' does not support AVC notifications", attrName)
+	//		return me.NewProcessingError(msg)
+	//	}
+	//}
+	bytes, err := b.AppendBytes(2)
+	if err != nil {
+		return err
+	}
+	binary.BigEndian.PutUint16(bytes, omci.AttributeMask)
+
+	// Attribute serialization
+	// TODO: Only Baseline supported at this time
+	bytesAvailable := MaxBaselineLength - 10 - 8
+
+	err, _ = meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask, b,
+		byte(AttributeValueChangeType), bytesAvailable, false)
+	return err
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// TestRequest:		TODO: Not yet implemented
+type TestRequest struct {
+	MeBasePacket
+}
+
+func (omci *TestRequest) String() string {
+	return fmt.Sprintf("%v", omci.MeBasePacket.String())
+}
+
+// DecodeFromBytes decodes the given bytes of a Test Request into this layer
+func (omci *TestRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	return errors.New("need to implement") // TODO: Fix me) // return nil
+}
+
+func decodeTestRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &TestRequest{}
+	omci.MsgLayerType = LayerTypeTestRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Test Request message
+func (omci *TestRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	return errors.New("need to implement") // TODO: Fix me) // omci.cachedME.SerializeTo(mask, b)
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// TestResponse:		TODO: Not yet implemented
+type TestResponse struct {
+	MeBasePacket
+}
+
+func (omci *TestResponse) String() string {
+	return fmt.Sprintf("%v", omci.MeBasePacket.String())
+}
+
+// DecodeFromBytes decodes the given bytes of a Test Response into this layer
+func (omci *TestResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	return errors.New("need to implement") // TODO: Fix me) // return nil
+}
+
+func decodeTestResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &TestResponse{}
+	omci.MsgLayerType = LayerTypeTestResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Test Response message
+func (omci *TestResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	return errors.New("need to implement") // TODO: Fix me) // omci.cachedME.SerializeTo(mask, b)
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type StartSoftwareDownloadRequest struct {
+	MeBasePacket                // Note: EntityInstance for software download is two specific values
+	WindowSize           byte   // Window Size -1
+	ImageSize            uint32 // Octets
+	NumberOfCircuitPacks byte
+	CircuitPacks         []uint16 // MSB & LSB of software image instance
+}
+
+func (omci *StartSoftwareDownloadRequest) String() string {
+	return fmt.Sprintf("%v, Window Size: %v, Image Size: %v, # Circuit Packs: %v",
+		omci.MeBasePacket.String(), omci.WindowSize, omci.ImageSize, omci.NumberOfCircuitPacks)
+}
+
+// DecodeFromBytes decodes the given bytes of a Start Software Download Request into this layer
+func (omci *StartSoftwareDownloadRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Start Software Download
+	if !me.SupportsMsgType(meDefinition, me.StartSoftwareDownload) {
+		return me.NewProcessingError("managed entity does not support Start Software Download Message-Type")
+	}
+	// Software Image Entity Class are always use the Software Image
+	if omci.EntityClass != me.SoftwareImageClassID {
+		return me.NewProcessingError("invalid Entity Class for Start Software Download request")
+	}
+	omci.WindowSize = data[4]
+	omci.ImageSize = binary.BigEndian.Uint32(data[5:9])
+	omci.NumberOfCircuitPacks = data[9]
+	if omci.NumberOfCircuitPacks < 1 || omci.NumberOfCircuitPacks > 9 {
+		return me.NewProcessingError(fmt.Sprintf("invalid number of Circuit Packs: %v, must be 1..9",
+			omci.NumberOfCircuitPacks))
+	}
+	omci.CircuitPacks = make([]uint16, omci.NumberOfCircuitPacks)
+	for index := 0; index < int(omci.NumberOfCircuitPacks); index++ {
+		omci.CircuitPacks[index] = binary.BigEndian.Uint16(data[10+(index*2):])
+	}
+	return nil
+}
+
+func decodeStartSoftwareDownloadRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &StartSoftwareDownloadRequest{}
+	omci.MsgLayerType = LayerTypeStartSoftwareDownloadRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Start Software Download Request message
+func (omci *StartSoftwareDownloadRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Start Software Download
+	if !me.SupportsMsgType(entity, me.StartSoftwareDownload) {
+		return me.NewProcessingError("managed entity does not support the SStart Software Download Message-Type")
+	}
+	// Software Image Entity Class are always use the Software Image
+	if omci.EntityClass != me.SoftwareImageClassID {
+		return me.NewProcessingError("invalid Entity Class for Start Software Download request")
+	}
+	if omci.NumberOfCircuitPacks < 1 || omci.NumberOfCircuitPacks > 9 {
+		return me.NewProcessingError(fmt.Sprintf("invalid number of Circuit Packs: %v, must be 1..9",
+			omci.NumberOfCircuitPacks))
+	}
+	bytes, err := b.AppendBytes(6 + (2 * int(omci.NumberOfCircuitPacks)))
+	if err != nil {
+		return err
+	}
+	bytes[0] = omci.WindowSize
+	binary.BigEndian.PutUint32(bytes[1:], omci.ImageSize)
+	bytes[5] = omci.NumberOfCircuitPacks
+	for index := 0; index < int(omci.NumberOfCircuitPacks); index++ {
+		binary.BigEndian.PutUint16(bytes[6+(index*2):], omci.CircuitPacks[index])
+	}
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type downloadResults struct {
+	ManagedEntityID uint16 // ME ID of software image entity instance (slot number plus instance 0..1 or 2..254 vendor-specific)
+	Result          me.Results
+}
+
+func (dr *downloadResults) String() string {
+	return fmt.Sprintf("ME: %v (%#x), Results: %d (%v)", dr.ManagedEntityID, dr.ManagedEntityID,
+		dr.Result, dr.Result)
+}
+
+type StartSoftwareDownloadResponse struct {
+	MeBasePacket      // Note: EntityInstance for software download is two specific values
+	Result            me.Results
+	WindowSize        byte // Window Size -1
+	NumberOfInstances byte
+	MeResults         []downloadResults
+}
+
+func (omci *StartSoftwareDownloadResponse) String() string {
+	return fmt.Sprintf("%v, Results: %v, Window Size: %v, # of Instances: %v, ME Results: %v",
+		omci.MeBasePacket.String(), omci.Result, omci.WindowSize, omci.NumberOfInstances, omci.MeResults)
+}
+
+// DecodeFromBytes decodes the given bytes of a Start Software Download Response into this layer
+func (omci *StartSoftwareDownloadResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Start Software Download
+	if !me.SupportsMsgType(meDefinition, me.StartSoftwareDownload) {
+		return me.NewProcessingError("managed entity does not support Start Software Download Message-Type")
+	}
+	// Software Image Entity Class are always use the Software Image
+	if omci.EntityClass != me.SoftwareImageClassID {
+		return me.NewProcessingError("invalid Entity Class for Start Software Download response")
+	}
+	omci.Result = me.Results(data[4])
+	if omci.Result > me.DeviceBusy {
+		msg := fmt.Sprintf("invalid results for Start Software Download response: %v, must be 0..6",
+			omci.Result)
+		return errors.New(msg)
+	}
+	omci.WindowSize = data[5]
+	omci.NumberOfInstances = data[6]
+
+	if omci.NumberOfInstances > 9 {
+		msg := fmt.Sprintf("invalid number of Circuit Packs: %v, must be 0..9",
+			omci.NumberOfInstances)
+		return errors.New(msg)
+	}
+	if omci.NumberOfInstances > 0 {
+		omci.MeResults = make([]downloadResults, omci.NumberOfInstances)
+
+		for index := 0; index < int(omci.NumberOfInstances); index++ {
+			omci.MeResults[index].ManagedEntityID = binary.BigEndian.Uint16(data[7+(index*3):])
+			omci.MeResults[index].Result = me.Results(data[9+(index*3)])
+			if omci.MeResults[index].Result > me.DeviceBusy {
+				msg := fmt.Sprintf("invalid results for Start Software Download instance %v response: %v, must be 0..6",
+					index, omci.MeResults[index])
+				return errors.New(msg)
+			}
+		}
+	}
+	return nil
+}
+
+func decodeStartSoftwareDownloadResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &StartSoftwareDownloadResponse{}
+	omci.MsgLayerType = LayerTypeStartSoftwareDownloadResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Start Software Download Response message
+func (omci *StartSoftwareDownloadResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Start Software Download
+	if !me.SupportsMsgType(meDefinition, me.StartSoftwareDownload) {
+		return me.NewProcessingError("managed entity does not support Start Software Download Message-Type")
+	}
+	// Software Image Entity Class are always use the Software Image
+	if omci.EntityClass != me.SoftwareImageClassID {
+		return me.NewProcessingError("invalid Entity Class for Start Software Download response")
+	}
+	bytes, err := b.AppendBytes(3 + (3 * int(omci.NumberOfInstances)))
+	if err != nil {
+		return err
+	}
+	if omci.Result > me.DeviceBusy {
+		msg := fmt.Sprintf("invalid results for Start Software Download response: %v, must be 0..6",
+			omci.Result)
+		return errors.New(msg)
+	}
+	bytes[0] = byte(omci.Result)
+	bytes[1] = omci.WindowSize
+	bytes[2] = omci.NumberOfInstances
+
+	if omci.NumberOfInstances > 9 {
+		msg := fmt.Sprintf("invalid number of Circuit Packs: %v, must be 0..9",
+			omci.NumberOfInstances)
+		return errors.New(msg)
+	}
+	if omci.NumberOfInstances > 0 {
+		for index := 0; index < int(omci.NumberOfInstances); index++ {
+			binary.BigEndian.PutUint16(bytes[3+(3*index):], omci.MeResults[index].ManagedEntityID)
+
+			if omci.MeResults[index].Result > me.DeviceBusy {
+				msg := fmt.Sprintf("invalid results for Start Software Download instance %v response: %v, must be 0..6",
+					index, omci.MeResults[index])
+				return errors.New(msg)
+			}
+			bytes[5+(3*index)] = byte(omci.MeResults[index].Result)
+		}
+	}
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type DownloadSectionRequest struct {
+	MeBasePacket  // Note: EntityInstance for software download is two specific values
+	SectionNumber byte
+	SectionData   [29]byte // 0 padding if final transfer requires only a partial block
+}
+
+func (omci *DownloadSectionRequest) String() string {
+	return fmt.Sprintf("%v, Section #: %v",
+		omci.MeBasePacket.String(), omci.SectionNumber)
+}
+
+// DecodeFromBytes decodes the given bytes of a Download Section Request into this layer
+func (omci *DownloadSectionRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Download section
+	if !me.SupportsMsgType(meDefinition, me.DownloadSection) {
+		return me.NewProcessingError("managed entity does not support Download Section Message-Type")
+	}
+	// Software Image Entity Class are always use the Software Image
+	if omci.EntityClass != me.SoftwareImageClassID {
+		return me.NewProcessingError("invalid Entity Class for Download Section request")
+	}
+	omci.SectionNumber = data[4]
+	copy(omci.SectionData[0:], data[5:])
+	return nil
+}
+
+func decodeDownloadSectionRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &DownloadSectionRequest{}
+	omci.MsgLayerType = LayerTypeDownloadSectionRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Download Section Request message
+func (omci *DownloadSectionRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Download section
+	if !me.SupportsMsgType(meDefinition, me.DownloadSection) {
+		return me.NewProcessingError("managed entity does not support Download Section Message-Type")
+	}
+	// Software Image Entity Class are always use the Software Image
+	if omci.EntityClass != me.SoftwareImageClassID {
+		return me.NewProcessingError("invalid Entity Class for Download Section response")
+	}
+	bytes, err := b.AppendBytes(1 + 29)
+	if err != nil {
+		return err
+	}
+	bytes[0] = omci.SectionNumber
+	copy(bytes[1:], omci.SectionData[0:])
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type DownloadSectionResponse struct {
+	MeBasePacket  // Note: EntityInstance for software download is two specific values
+	Result        me.Results
+	SectionNumber byte
+}
+
+func (omci *DownloadSectionResponse) String() string {
+	return fmt.Sprintf("%v, Result: %d (%v), Section #: %v",
+		omci.MeBasePacket.String(), omci.Result, omci.Result, omci.SectionNumber)
+}
+
+// DecodeFromBytes decodes the given bytes of a Download Section Response into this layer
+func (omci *DownloadSectionResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Download section
+	if !me.SupportsMsgType(meDefinition, me.DownloadSection) {
+		return me.NewProcessingError("managed entity does not support Download Section Message-Type")
+	}
+	// Software Image Entity Class are always use the Software Image
+	if omci.EntityClass != me.SoftwareImageClassID {
+		return me.NewProcessingError("invalid Entity Class for Download Section response")
+	}
+	omci.Result = me.Results(data[4])
+	if omci.Result > me.DeviceBusy {
+		msg := fmt.Sprintf("invalid results for Download Section response: %v, must be 0..6",
+			omci.Result)
+		return errors.New(msg)
+	}
+	omci.SectionNumber = data[5]
+	return nil
+}
+
+func decodeDownloadSectionResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &DownloadSectionResponse{}
+	omci.MsgLayerType = LayerTypeDownloadSectionResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Download Section Response message
+func (omci *DownloadSectionResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Download section
+	if !me.SupportsMsgType(meDefinition, me.DownloadSection) {
+		return me.NewProcessingError("managed entity does not support Download Section Message-Type")
+	}
+	// Software Image Entity Class are always use the Software Image
+	if omci.EntityClass != me.SoftwareImageClassID {
+		return me.NewProcessingError("invalid Entity Class for Download Section response")
+	}
+	bytes, err := b.AppendBytes(2)
+	if err != nil {
+		return err
+	}
+	bytes[0] = omci.SectionNumber
+	if omci.Result > me.DeviceBusy {
+		msg := fmt.Sprintf("invalid results for Download Section response: %v, must be 0..6",
+			omci.Result)
+		return errors.New(msg)
+	}
+	bytes[1] = byte(omci.Result)
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type EndSoftwareDownloadRequest struct {
+	MeBasePacket      // Note: EntityInstance for software download is two specific values
+	CRC32             uint32
+	ImageSize         uint32
+	NumberOfInstances byte
+	ImageInstances    []uint16
+}
+
+func (omci *EndSoftwareDownloadRequest) String() string {
+	return fmt.Sprintf("%v, CRC: %#x, Image Size: %v, Number of Instances: %v, Instances: %v",
+		omci.MeBasePacket.String(), omci.CRC32, omci.ImageSize, omci.NumberOfInstances, omci.ImageInstances)
+}
+
+// DecodeFromBytes decodes the given bytes of an End Software Download Request into this layer
+func (omci *EndSoftwareDownloadRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support End Software Download
+	if !me.SupportsMsgType(meDefinition, me.EndSoftwareDownload) {
+		return me.NewProcessingError("managed entity does not support End Software Download Message-Type")
+	}
+	// Software Image Entity Class are always use the Software Image
+	if omci.EntityClass != me.SoftwareImageClassID {
+		return me.NewProcessingError("invalid Entity Class for End Software Download request")
+	}
+	omci.CRC32 = binary.BigEndian.Uint32(data[4:8])
+	omci.ImageSize = binary.BigEndian.Uint32(data[8:12])
+	omci.NumberOfInstances = data[13]
+
+	if omci.NumberOfInstances < 1 || omci.NumberOfInstances > 9 {
+		return me.NewProcessingError(fmt.Sprintf("invalid number of Instances: %v, must be 1..9",
+			omci.NumberOfInstances))
+	}
+	omci.ImageInstances = make([]uint16, omci.NumberOfInstances)
+
+	for index := 0; index < int(omci.NumberOfInstances); index++ {
+		omci.ImageInstances[index] = binary.BigEndian.Uint16(data[14+(index*2):])
+	}
+	return nil
+}
+
+func decodeEndSoftwareDownloadRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &EndSoftwareDownloadRequest{}
+	omci.MsgLayerType = LayerTypeEndSoftwareDownloadRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an End Software Download Request message
+func (omci *EndSoftwareDownloadRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support End Software Download
+	if !me.SupportsMsgType(meDefinition, me.EndSoftwareDownload) {
+		return me.NewProcessingError("managed entity does not support Start End Download Message-Type")
+	}
+	// Software Image Entity Class are always use the Software Image
+	if omci.EntityClass != me.SoftwareImageClassID {
+		return me.NewProcessingError("invalid Entity Class for End Software Download response")
+	}
+	if omci.NumberOfInstances < 1 || omci.NumberOfInstances > 9 {
+		return me.NewProcessingError(fmt.Sprintf("invalid number of Instances: %v, must be 1..9",
+			omci.NumberOfInstances))
+	}
+	bytes, err := b.AppendBytes(9 + (2 * int(omci.NumberOfInstances)))
+	if err != nil {
+		return err
+	}
+	binary.BigEndian.PutUint32(bytes[4:8], omci.CRC32)
+	binary.BigEndian.PutUint32(bytes[8:12], omci.ImageSize)
+	bytes[13] = omci.NumberOfInstances
+	for index := 0; index < int(omci.NumberOfInstances); index++ {
+		binary.BigEndian.PutUint16(bytes[14+(index*2):], omci.ImageInstances[index])
+	}
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type EndSoftwareDownloadResponse struct {
+	MeBasePacket      // Note: EntityInstance for software download is two specific values
+	Result            me.Results
+	NumberOfInstances byte
+	MeResults         []downloadResults
+}
+
+func (omci *EndSoftwareDownloadResponse) String() string {
+	return fmt.Sprintf("%v, Result: %d (%v), Number of Instances: %v, ME Results: %v",
+		omci.MeBasePacket.String(), omci.Result, omci.Result, omci.NumberOfInstances, omci.MeResults)
+}
+
+// DecodeFromBytes decodes the given bytes of an End Software Download Response into this layer
+func (omci *EndSoftwareDownloadResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support End Software Download
+	if !me.SupportsMsgType(meDefinition, me.EndSoftwareDownload) {
+		return me.NewProcessingError("managed entity does not support End Software Download Message-Type")
+	}
+	// Software Image Entity Class are always use the Software Image
+	if omci.EntityClass != me.SoftwareImageClassID {
+		return me.NewProcessingError("invalid Entity Class for End Software Download response")
+	}
+	omci.Result = me.Results(data[4])
+	if omci.Result > me.DeviceBusy {
+		msg := fmt.Sprintf("invalid results for End Software Download response: %v, must be 0..6",
+			omci.Result)
+		return errors.New(msg)
+	}
+	omci.NumberOfInstances = data[5]
+
+	if omci.NumberOfInstances > 9 {
+		msg := fmt.Sprintf("invalid number of Instances: %v, must be 0..9",
+			omci.NumberOfInstances)
+		return errors.New(msg)
+	}
+	if omci.NumberOfInstances > 0 {
+		omci.MeResults = make([]downloadResults, omci.NumberOfInstances)
+
+		for index := 0; index < int(omci.NumberOfInstances); index++ {
+			omci.MeResults[index].ManagedEntityID = binary.BigEndian.Uint16(data[6+(index*3):])
+			omci.MeResults[index].Result = me.Results(data[8+(index*3)])
+			if omci.MeResults[index].Result > me.DeviceBusy {
+				msg := fmt.Sprintf("invalid results for End Software Download instance %v response: %v, must be 0..6",
+					index, omci.MeResults[index])
+				return errors.New(msg)
+			}
+		}
+	}
+	return nil
+}
+
+func decodeEndSoftwareDownloadResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &EndSoftwareDownloadResponse{}
+	omci.MsgLayerType = LayerTypeEndSoftwareDownloadResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an End Software Download Response message
+func (omci *EndSoftwareDownloadResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support End Software Download
+	if !me.SupportsMsgType(meDefinition, me.EndSoftwareDownload) {
+		return me.NewProcessingError("managed entity does not support End End Download Message-Type")
+	}
+	// Software Image Entity Class are always use the Software Image
+	if omci.EntityClass != me.SoftwareImageClassID {
+		return me.NewProcessingError("invalid Entity Class for End Download response")
+	}
+	bytes, err := b.AppendBytes(3 + (3 * int(omci.NumberOfInstances)))
+	if err != nil {
+		return err
+	}
+	if omci.Result > me.DeviceBusy {
+		msg := fmt.Sprintf("invalid results for End Software Download response: %v, must be 0..6",
+			omci.Result)
+		return errors.New(msg)
+	}
+	bytes[0] = byte(omci.Result)
+	bytes[1] = omci.NumberOfInstances
+
+	if omci.NumberOfInstances > 9 {
+		msg := fmt.Sprintf("invalid number of Instances: %v, must be 0..9",
+			omci.NumberOfInstances)
+		return errors.New(msg)
+	}
+	if omci.NumberOfInstances > 0 {
+		for index := 0; index < int(omci.NumberOfInstances); index++ {
+			binary.BigEndian.PutUint16(bytes[2+(3*index):], omci.MeResults[index].ManagedEntityID)
+
+			if omci.MeResults[index].Result > me.DeviceBusy {
+				msg := fmt.Sprintf("invalid results for End Software Download instance %v response: %v, must be 0..6",
+					index, omci.MeResults[index])
+				return errors.New(msg)
+			}
+			bytes[4+(3*index)] = byte(omci.MeResults[index].Result)
+		}
+	}
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type ActivateSoftwareRequest struct {
+	MeBasePacket  // Note: EntityInstance for software download is two specific values
+	ActivateFlags byte
+}
+
+func (omci *ActivateSoftwareRequest) String() string {
+	return fmt.Sprintf("%v, Flags: %#x",
+		omci.MeBasePacket.String(), omci.ActivateFlags)
+}
+
+// DecodeFromBytes decodes the given bytes of an Activate Software Request into this layer
+func (omci *ActivateSoftwareRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support End Software Download
+	if !me.SupportsMsgType(meDefinition, me.ActivateSoftware) {
+		return me.NewProcessingError("managed entity does not support Activate Software Message-Type")
+	}
+	// Software Image Entity Class are always use the Software Image
+	if omci.EntityClass != me.SoftwareImageClassID {
+		return me.NewProcessingError("invalid Entity Class for Activate Software request")
+	}
+	omci.ActivateFlags = data[4]
+	if omci.ActivateFlags > 2 {
+		return me.NewProcessingError(fmt.Sprintf("invalid number of Activation flangs: %v, must be 0..2",
+			omci.ActivateFlags))
+	}
+	return nil
+}
+
+func decodeActivateSoftwareRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &ActivateSoftwareRequest{}
+	omci.MsgLayerType = LayerTypeActivateSoftwareRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Activate Software message
+func (omci *ActivateSoftwareRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support End Software Download
+	if !me.SupportsMsgType(meDefinition, me.ActivateSoftware) {
+		return me.NewProcessingError("managed entity does not support Activate Message-Type")
+	}
+	// Software Image Entity Class are always use the Software Image
+	if omci.EntityClass != me.SoftwareImageClassID {
+		return me.NewProcessingError("invalid Entity Class for Activate Software request")
+	}
+	bytes, err := b.AppendBytes(1)
+	if err != nil {
+		return err
+	}
+	bytes[0] = omci.ActivateFlags
+	if omci.ActivateFlags > 2 {
+		msg := fmt.Sprintf("invalid results for Activate Software request: %v, must be 0..2",
+			omci.ActivateFlags)
+		return errors.New(msg)
+	}
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type ActivateSoftwareResponse struct {
+	MeBasePacket
+	Result me.Results
+}
+
+func (omci *ActivateSoftwareResponse) String() string {
+	return fmt.Sprintf("%v, Result: %d (%v)",
+		omci.MeBasePacket.String(), omci.Result, omci.Result)
+}
+
+// DecodeFromBytes decodes the given bytes of an Activate Softwre Response into this layer
+func (omci *ActivateSoftwareResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support End Software Download
+	if !me.SupportsMsgType(meDefinition, me.ActivateSoftware) {
+		return me.NewProcessingError("managed entity does not support Activate Software Message-Type")
+	}
+	// Software Image Entity Class are always use the Software Image
+	if omci.EntityClass != me.SoftwareImageClassID {
+		return me.NewProcessingError("invalid Entity Class for Activate Software response")
+	}
+	omci.Result = me.Results(data[4])
+	if omci.Result > me.Results(6) {
+		msg := fmt.Sprintf("invalid results for Activate Software response: %v, must be 0..6",
+			omci.Result)
+		return errors.New(msg)
+	}
+	return nil
+}
+
+func decodeActivateSoftwareResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &ActivateSoftwareResponse{}
+	omci.MsgLayerType = LayerTypeActivateSoftwareResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Activate Software Response message
+func (omci *ActivateSoftwareResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support End Software Download
+	if !me.SupportsMsgType(meDefinition, me.ActivateSoftware) {
+		return me.NewProcessingError("managed entity does not support Activate Message-Type")
+	}
+	// Software Image Entity Class are always use the Software Image
+	if omci.EntityClass != me.SoftwareImageClassID {
+		return me.NewProcessingError("invalid Entity Class for Activate Software response")
+	}
+	bytes, err := b.AppendBytes(1)
+	if err != nil {
+		return err
+	}
+	bytes[0] = byte(omci.Result)
+	if omci.Result > me.Results(6) {
+		msg := fmt.Sprintf("invalid results for Activate Software response: %v, must be 0..6",
+			omci.Result)
+		return errors.New(msg)
+	}
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type CommitSoftwareRequest struct {
+	MeBasePacket
+}
+
+func (omci *CommitSoftwareRequest) String() string {
+	return fmt.Sprintf("%v", omci.MeBasePacket.String())
+}
+
+// DecodeFromBytes decodes the given bytes of a Commit Software Request into this layer
+func (omci *CommitSoftwareRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support End Software Download
+	if !me.SupportsMsgType(meDefinition, me.CommitSoftware) {
+		return me.NewProcessingError("managed entity does not support Commit Software Message-Type")
+	}
+	// Software Image Entity Class are always use the Software Image
+	if omci.EntityClass != me.SoftwareImageClassID {
+		return me.NewProcessingError("invalid Entity Class for Commit Software request")
+	}
+	return nil
+}
+
+func decodeCommitSoftwareRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &CommitSoftwareRequest{}
+	omci.MsgLayerType = LayerTypeCommitSoftwareRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Commit Software Request message
+func (omci *CommitSoftwareRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support End Software Download
+	if !me.SupportsMsgType(meDefinition, me.CommitSoftware) {
+		return me.NewProcessingError("managed entity does not support Commit Message-Type")
+	}
+	// Software Image Entity Class are always use the Software Image
+	if omci.EntityClass != me.SoftwareImageClassID {
+		return me.NewProcessingError("invalid Entity Class for Commit Software request")
+	}
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type CommitSoftwareResponse struct {
+	MeBasePacket
+}
+
+func (omci *CommitSoftwareResponse) String() string {
+	return fmt.Sprintf("%v", omci.MeBasePacket.String())
+}
+
+// DecodeFromBytes decodes the given bytes of a Commit Softwar Response into this layer
+func (omci *CommitSoftwareResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support End Software Download
+	if !me.SupportsMsgType(meDefinition, me.CommitSoftware) {
+		return me.NewProcessingError("managed entity does not support Commit Software Message-Type")
+	}
+	// Software Image Entity Class are always use the Software Image
+	if omci.EntityClass != me.SoftwareImageClassID {
+		return me.NewProcessingError("invalid Entity Class for Commit Software response")
+	}
+	return nil
+}
+
+func decodeCommitSoftwareResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &CommitSoftwareResponse{}
+	omci.MsgLayerType = LayerTypeCommitSoftwareResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Commit Software Response message
+func (omci *CommitSoftwareResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support End Software Download
+	if !me.SupportsMsgType(meDefinition, me.CommitSoftware) {
+		return me.NewProcessingError("managed entity does not support Commit Message-Type")
+	}
+	// Software Image Entity Class are always use the Software Image
+	if omci.EntityClass != me.SoftwareImageClassID {
+		return me.NewProcessingError("invalid Entity Class for Commit Software response")
+	}
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type SynchronizeTimeRequest struct {
+	MeBasePacket
+	Year   uint16
+	Month  uint8
+	Day    uint8
+	Hour   uint8
+	Minute uint8
+	Second uint8
+}
+
+func (omci *SynchronizeTimeRequest) String() string {
+	return fmt.Sprintf("%v, Date-Time: %d/%d/%d-%02d:%02d:%02d",
+		omci.MeBasePacket.String(), omci.Year, omci.Month, omci.Day, omci.Hour, omci.Minute, omci.Second)
+}
+
+// DecodeFromBytes decodes the given bytes of a Synchronize Time Request into this layer
+func (omci *SynchronizeTimeRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Synchronize Time
+	if !me.SupportsMsgType(meDefinition, me.SynchronizeTime) {
+		return me.NewProcessingError("managed entity does not support Synchronize Time Message-Type")
+	}
+	// Synchronize Time Entity Class are always ONU-G (256) and Entity Instance of 0
+	if omci.EntityClass != me.OnuGClassID {
+		return me.NewProcessingError("invalid Entity Class for Synchronize Time request")
+	}
+	if omci.EntityInstance != 0 {
+		return me.NewUnknownInstanceError("invalid Entity Instance for Synchronize Time request")
+	}
+	omci.Year = binary.BigEndian.Uint16(data[4:6])
+	omci.Month = data[6]
+	omci.Day = data[7]
+	omci.Hour = data[8]
+	omci.Minute = data[9]
+	omci.Second = data[10]
+	return nil
+}
+
+func decodeSynchronizeTimeRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &SynchronizeTimeRequest{}
+	omci.MsgLayerType = LayerTypeSynchronizeTimeRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Synchronize Time Request message
+func (omci *SynchronizeTimeRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Synchronize Time
+	if !me.SupportsMsgType(entity, me.SynchronizeTime) {
+		return me.NewProcessingError("managed entity does not support the Synchronize Time Message-Type")
+	}
+	bytes, err := b.AppendBytes(7)
+	if err != nil {
+		return err
+	}
+	binary.BigEndian.PutUint16(bytes[0:2], omci.Year)
+	bytes[2] = omci.Month
+	bytes[3] = omci.Day
+	bytes[4] = omci.Hour
+	bytes[5] = omci.Minute
+	bytes[6] = omci.Second
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type SynchronizeTimeResponse struct {
+	MeBasePacket
+	Result         me.Results
+	SuccessResults uint8 // Only if 'Result' is 0 -> success
+}
+
+func (omci *SynchronizeTimeResponse) String() string {
+	return fmt.Sprintf("%v, Results: %d (%v), Success: %d",
+		omci.MeBasePacket.String(), omci.Result, omci.Result, omci.SuccessResults)
+}
+
+// DecodeFromBytes decodes the given bytes of a Synchronize Time Response into this layer
+func (omci *SynchronizeTimeResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Synchronize Time
+	if !me.SupportsMsgType(meDefinition, me.SynchronizeTime) {
+		return me.NewProcessingError("managed entity does not support Synchronize Time Message-Type")
+	}
+	// Synchronize Time Entity Class are always ONU-G (256) and Entity Instance of 0
+	if omci.EntityClass != me.OnuGClassID {
+		return me.NewProcessingError("invalid Entity Class for Synchronize Time response")
+	}
+	if omci.EntityInstance != 0 {
+		return me.NewUnknownInstanceError("invalid Entity Instance for Synchronize Time response")
+	}
+	omci.Result = me.Results(data[4])
+	if omci.Result > me.DeviceBusy {
+		msg := fmt.Sprintf("invalid results code: %v, must be 0..8", omci.Result)
+		return errors.New(msg)
+	}
+	omci.SuccessResults = data[5]
+	return nil
+}
+
+func decodeSynchronizeTimeResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &SynchronizeTimeResponse{}
+	omci.MsgLayerType = LayerTypeSynchronizeTimeResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Synchronize Time Response message
+func (omci *SynchronizeTimeResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// Synchronize Time Entity Class are always ONU DATA (2) and Entity Instance of 0
+	if omci.EntityClass != me.OnuGClassID {
+		return me.NewProcessingError("invalid Entity Class for Synchronize Time response")
+	}
+	if omci.EntityInstance != 0 {
+		return me.NewUnknownInstanceError("invalid Entity Instance for Synchronize Time response")
+	}
+	// ME needs to support Synchronize Time
+	if !me.SupportsMsgType(entity, me.SynchronizeTime) {
+		return me.NewProcessingError("managed entity does not support the Synchronize Time Message-Type")
+	}
+	numBytes := 2
+	if omci.Result != me.Success {
+		numBytes = 1
+	}
+	bytes, err := b.AppendBytes(numBytes)
+	if err != nil {
+		return err
+	}
+	bytes[0] = uint8(omci.Result)
+	if omci.Result == me.Success {
+		bytes[1] = omci.SuccessResults
+	}
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type RebootRequest struct {
+	MeBasePacket
+	RebootCondition byte
+}
+
+func (omci *RebootRequest) String() string {
+	return fmt.Sprintf("%v, Reboot Condition: %v",
+		omci.MeBasePacket.String(), omci.RebootCondition)
+}
+
+// DecodeFromBytes decodes the given bytes of a Reboot Request into this layer
+func (omci *RebootRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Reboot
+	if !me.SupportsMsgType(meDefinition, me.Reboot) {
+		return me.NewProcessingError("managed entity does not support Reboot Message-Type")
+	}
+	omci.RebootCondition = data[4]
+	if omci.RebootCondition > 3 {
+		msg := fmt.Sprintf("invalid reboot condition code: %v, must be 0..3", omci.RebootCondition)
+		return errors.New(msg)
+	}
+	return nil
+}
+
+func decodeRebootRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &RebootRequest{}
+	omci.MsgLayerType = LayerTypeRebootRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Reboot Request message
+func (omci *RebootRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Reboot
+	if !me.SupportsMsgType(entity, me.Reboot) {
+		return me.NewProcessingError("managed entity does not support the Synchronize Time Message-Type")
+	}
+	bytes, err := b.AppendBytes(1)
+	if err != nil {
+		return err
+	}
+	if omci.RebootCondition > 3 {
+		return me.NewProcessingError(fmt.Sprintf("invalid reboot condition code: %v, must be 0..3",
+			omci.RebootCondition))
+	}
+	bytes[0] = omci.RebootCondition
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type RebootResponse struct {
+	MeBasePacket
+	Result me.Results
+}
+
+// DecodeFromBytes decodes the given bytes of a Reboot Response into this layer
+func (omci *RebootResponse) String() string {
+	return fmt.Sprintf("%v, Result: %d (%v)",
+		omci.MeBasePacket.String(), omci.Result, omci.Result)
+}
+
+// DecodeFromBytes decodes the given bytes of a Reboot Response into this layer
+func (omci *RebootResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Reboot
+	if !me.SupportsMsgType(meDefinition, me.Reboot) {
+		return me.NewProcessingError("managed entity does not support Reboot Message-Type")
+	}
+	if omci.Result > 6 {
+		msg := fmt.Sprintf("invalid reboot results code: %v, must be 0..6", omci.Result)
+		return errors.New(msg)
+	}
+	omci.Result = me.Results(data[4])
+	return nil
+}
+
+func decodeRebootResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &RebootResponse{}
+	omci.MsgLayerType = LayerTypeRebootResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Reboot Response message
+func (omci *RebootResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Reboot
+	if !me.SupportsMsgType(entity, me.Reboot) {
+		return me.NewProcessingError("managed entity does not support the Synchronize Time Message-Type")
+	}
+	bytes, err := b.AppendBytes(1)
+	if err != nil {
+		return err
+	}
+	if omci.Result > 6 {
+		msg := fmt.Sprintf("invalid reboot results code: %v, must be 0..6", omci.Result)
+		return errors.New(msg)
+	}
+	bytes[0] = byte(omci.Result)
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type GetNextRequest struct {
+	MeBasePacket
+	AttributeMask  uint16
+	SequenceNumber uint16
+}
+
+func (omci *GetNextRequest) String() string {
+	return fmt.Sprintf("%v, Attribute Mask: %#x, Sequence Number: %v",
+		omci.MeBasePacket.String(), omci.AttributeMask, omci.SequenceNumber)
+}
+
+// DecodeFromBytes decodes the given bytes of a Get Next Request into this layer
+func (omci *GetNextRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support GetNext
+	if !me.SupportsMsgType(meDefinition, me.GetNext) {
+		return me.NewProcessingError("managed entity does not support Get Next Message-Type")
+	}
+	// Note: G.988 specifies that an error code of (3) should result if more
+	//       than one attribute is requested
+	// TODO: Return error.  Have flag to optionally allow it to be encoded
+	// TODO: Check that the attribute is a table attirbute.  Issue warning or return error
+	omci.AttributeMask = binary.BigEndian.Uint16(data[4:6])
+	omci.SequenceNumber = binary.BigEndian.Uint16(data[6:8])
+	return nil
+}
+
+func decodeGetNextRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetNextRequest{}
+	omci.MsgLayerType = LayerTypeGetNextRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Get Next Message Type Request
+func (omci *GetNextRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support GetNext
+	if !me.SupportsMsgType(meDefinition, me.GetNext) {
+		return me.NewProcessingError("managed entity does not support Get Next Message-Type")
+	}
+	bytes, err := b.AppendBytes(4)
+	if err != nil {
+		return err
+	}
+	binary.BigEndian.PutUint16(bytes, omci.AttributeMask)
+	binary.BigEndian.PutUint16(bytes[2:], omci.SequenceNumber)
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type GetNextResponse struct {
+	MeBasePacket
+	Result        me.Results
+	AttributeMask uint16
+	Attributes    me.AttributeValueMap
+}
+
+// SerializeTo provides serialization of an Get Next Message Type Response
+func (omci *GetNextResponse) String() string {
+	return fmt.Sprintf("%v, Result: %v, Attribute Mask: %#x, Attributes: %v",
+		omci.MeBasePacket.String(), omci.Result, omci.AttributeMask, omci.Attributes)
+}
+
+// DecodeFromBytes decodes the given bytes of a Get Next Response into this layer
+func (omci *GetNextResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Set
+	if !me.SupportsMsgType(meDefinition, me.GetNext) {
+		return me.NewProcessingError("managed entity does not support Get Next Message-Type")
+	}
+	omci.Result = me.Results(data[4])
+	if omci.Result > 6 {
+		msg := fmt.Sprintf("invalid get next results code: %v, must be 0..6", omci.Result)
+		return errors.New(msg)
+	}
+	omci.AttributeMask = binary.BigEndian.Uint16(data[5:7])
+
+	// Attribute decode
+	omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask, data[7:], p, byte(GetNextResponseType))
+	if err != nil {
+		return err
+	}
+	// Validate all attributes support read
+	for attrName := range omci.Attributes {
+		attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
+		if err != nil {
+			return err
+		}
+		if attr.Index != 0 && !me.SupportsAttributeAccess(*attr, me.Read) {
+			msg := fmt.Sprintf("attribute '%v' does not support read access", attrName)
+			return me.NewProcessingError(msg)
+		}
+	}
+	if eidDef, eidDefOK := meDefinition.GetAttributeDefinitions()[0]; eidDefOK {
+		omci.Attributes[eidDef.GetName()] = omci.EntityInstance
+		return nil
+	}
+	panic("All Managed Entities have an EntityID attribute")
+}
+
+func decodeGetNextResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetNextResponse{}
+	omci.MsgLayerType = LayerTypeGetNextResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Get Next Message Type Response
+func (omci *GetNextResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Get
+	if !me.SupportsMsgType(meDefinition, me.GetNext) {
+		return me.NewProcessingError("managed entity does not support the Get Next Message-Type")
+	}
+	bytes, err := b.AppendBytes(3)
+	if err != nil {
+		return err
+	}
+	bytes[0] = byte(omci.Result)
+	if omci.Result > 6 {
+		msg := fmt.Sprintf("invalid get next results code: %v, must be 0..6", omci.Result)
+		return errors.New(msg)
+	}
+	binary.BigEndian.PutUint16(bytes[1:3], omci.AttributeMask)
+
+	// Validate all attributes support read
+	for attrName := range omci.Attributes {
+		attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
+		if err != nil {
+			return err
+		}
+		if attr.Index != 0 && !me.SupportsAttributeAccess(*attr, me.Read) {
+			msg := fmt.Sprintf("attribute '%v' does not support read access", attrName)
+			return me.NewProcessingError(msg)
+		}
+	}
+	// Attribute serialization
+	switch omci.Result {
+	default:
+		break
+
+	case me.Success:
+		// TODO: Only Baseline supported at this time
+		bytesAvailable := MaxBaselineLength - 11 - 8
+
+		err, _ = meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask, b,
+			byte(GetNextResponseType), bytesAvailable, false)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type TestResultMsg struct {
+	MeBasePacket
+}
+
+func (omci *TestResultMsg) String() string {
+	return fmt.Sprintf("%v", omci.MeBasePacket.String())
+}
+
+// DecodeFromBytes decodes the given bytes of a Test Result Notification into this layer
+func (omci *TestResultMsg) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	return errors.New("need to implement") // TODO: Fix me) // return nil
+}
+
+func decodeTestResult(data []byte, p gopacket.PacketBuilder) error {
+	omci := &TestResultMsg{}
+	omci.MsgLayerType = LayerTypeTestResult
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Test Result notification message
+func (omci *TestResultMsg) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	return errors.New("need to implement") // TODO: Fix me) // omci.cachedME.SerializeTo(mask, b)
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type GetCurrentDataRequest struct {
+	MeBasePacket
+	AttributeMask uint16
+}
+
+func (omci *GetCurrentDataRequest) String() string {
+	return fmt.Sprintf("%v, Attribute Mask: %#x",
+		omci.MeBasePacket.String(), omci.AttributeMask)
+}
+
+// DecodeFromBytes decodes the given bytes of a Get Current Data Request into this layer
+func (omci *GetCurrentDataRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support GetNext
+	if !me.SupportsMsgType(meDefinition, me.GetCurrentData) {
+		return me.NewProcessingError("managed entity does not support Get Current Data Message-Type")
+	}
+	// Note: G.988 specifies that an error code of (3) should result if more
+	//       than one attribute is requested
+	omci.AttributeMask = binary.BigEndian.Uint16(data[4:6])
+	return nil
+}
+
+func decodeGetCurrentDataRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetCurrentDataRequest{}
+	omci.MsgLayerType = LayerTypeGetCurrentDataRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Get Current Data Request message
+func (omci *GetCurrentDataRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support GetNext
+	if !me.SupportsMsgType(meDefinition, me.GetCurrentData) {
+		return me.NewProcessingError("managed entity does not support Get Current Data Message-Type")
+	}
+	bytes, err := b.AppendBytes(2)
+	if err != nil {
+		return err
+	}
+	binary.BigEndian.PutUint16(bytes, omci.AttributeMask)
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type GetCurrentDataResponse struct {
+	MeBasePacket
+	Result        me.Results
+	AttributeMask uint16
+	Attributes    me.AttributeValueMap
+}
+
+func (omci *GetCurrentDataResponse) String() string {
+	return fmt.Sprintf("%v, Result: %d (%v), Attribute Mask: %#x, Attributes: %v",
+		omci.MeBasePacket.String(), omci.Result, omci.Result, omci.AttributeMask, omci.Attributes)
+}
+
+// DecodeFromBytes decodes the given bytes of a Get Current Data Respnse into this layer
+func (omci *GetCurrentDataResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Set
+	if !me.SupportsMsgType(meDefinition, me.GetCurrentData) {
+		return me.NewProcessingError("managed entity does not support Get Current Data Message-Type")
+	}
+	omci.AttributeMask = binary.BigEndian.Uint16(data[4:6])
+
+	// Attribute decode
+	omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask, data[6:], p, byte(GetCurrentDataResponseType))
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func decodeGetCurrentDataResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetCurrentDataResponse{}
+	omci.MsgLayerType = LayerTypeGetCurrentDataResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Get Current Data Message Type Response
+func (omci *GetCurrentDataResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// ME needs to support Get
+	if !me.SupportsMsgType(meDefinition, me.GetCurrentData) {
+		return me.NewProcessingError("managed entity does not support the Get Current Data Message-Type")
+	}
+	bytes, err := b.AppendBytes(2)
+	if err != nil {
+		return err
+	}
+	binary.BigEndian.PutUint16(bytes[0:2], omci.AttributeMask)
+
+	// Attribute serialization
+	// TODO: Only Baseline supported at this time
+	bytesAvailable := MaxBaselineLength - 9 - 8
+	var failedMask uint16
+
+	err, failedMask = meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask, b,
+		byte(GetCurrentDataResponseType), bytesAvailable, opts.FixLengths)
+
+	if failedMask != 0 {
+		// TODO: See GetResponse serialization above for the steps here
+		return me.NewMessageTruncatedError("getCurrentData attribute truncation not yet supported")
+	}
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type SetTableRequest struct {
+	MeBasePacket
+	// TODO: Fix me when extended messages supported)
+}
+
+func (omci *SetTableRequest) String() string {
+	return fmt.Sprintf("%v", omci.MeBasePacket.String())
+}
+
+// DecodeFromBytes decodes the given bytes of a Set Table Request into this layer
+func (omci *SetTableRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	return errors.New("need to implement") // TODO: Fix me when extended messages supported)
+}
+
+func decodeSetTableRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &SetTableRequest{}
+	omci.MsgLayerType = LayerTypeSetTableRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Set Table Message Type Request
+func (omci *SetTableRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	return errors.New("need to implement") /// TODO: Fix me when extended messages supported)
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type SetTableResponse struct {
+	MeBasePacket
+	// TODO: Fix me when extended messages supported)
+}
+
+func (omci *SetTableResponse) String() string {
+	return fmt.Sprintf("%v", omci.MeBasePacket.String())
+}
+
+// DecodeFromBytes decodes the given bytes of a Set Table Response into this layer
+func (omci *SetTableResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p)
+	if err != nil {
+		return err
+	}
+	return errors.New("need to implement") // TODO: Fix me when extended messages supported)
+}
+
+func decodeSetTableResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &SetTableResponse{}
+	omci.MsgLayerType = LayerTypeSetTableResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Set Table Message Type Response
+func (omci *SetTableResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	return errors.New("need to implement") // TODO: Fix me when extended messages supported)
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+type UnsupportedMessageTypeResponse struct {
+	MeBasePacket
+	Result me.Results
+}
+
+// DecodeFromBytes decodes the given bytes of an Unsupported Message Type Response into this layer
+func (omci *UnsupportedMessageTypeResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	return errors.New("you should never really decode this")
+}
+
+// SerializeTo provides serialization of an Unsupported Message Type Response
+func (omci *UnsupportedMessageTypeResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	bytes, err := b.AppendBytes(1)
+	if err != nil {
+		return err
+	}
+	bytes[0] = byte(omci.Result)
+	return nil
+}
