VOL-4337: Code upgrade for 3/2020 G.988 support and remaining Extended Message Set support

Change-Id: I6c5e1a167216ad9b51e9da89460e9909465ae1bc
diff --git a/README.md b/README.md
index a2aa972..829c877 100644
--- a/README.md
+++ b/README.md
@@ -1,137 +1,69 @@
 # OMCI
 
 OMCI gopacket library supports the encoding and decoding of ITU G.988 OMCI
-messages.  Support for the Baseline Message Set has been completed and work
-is underway to support the Extended Message Set format.
+messages. Support for the Baseline and Extended Message Set has been completed for
+basic serialization and decode and some support for the MEFrame library.
 
-## Message Types supported and under unit test
-The following OMCI message types currently have been coded and are covered
-satisfactory by unit tests.
+Future work is to focus on getting unit test coverage >= 75% for the basic serialization
+and decode objects before work for additional extended message set support in the
+MEFrame library.
 
- - CreateRequest
- - CreateResponse
- - DeleteRequest
- - DeleteResponse
- - SetRequest
- - GetRequest
- - GetAllAlarmsRequest
- - GetAllAlarmsResponse
- - GetAllAlarmsNextRequest
- - MibUploadRequest
- - MibUploadResponse
- - MibUploadNextRequest
- - MibResetRequest
- - MibResetResponse
- - SynchronizeTimeRequest
- - DownloadSectionRequest
- - DownloadSectionResponse
- - EndSoftwareDownloadRequest
- - EndSoftwareDownloadResponse
- - CommitSoftwareRequest
- - CommitSoftwareResponse
- - AlarmNotification
+# Recent Changes
 
-## Message Types supported but lacking full unit test
-The following OMCI message types currently have been coded and are partially covered
-by unit tests, but work still remains for sufficient/better unit test coverage.
+In v2.0.0, the directory/package structure was reorganized (no API changes otherwise)
+in order to separate message type functionality on a filename basis. This will allow
+for future features and bug fixes to be better localized and to allow for better
+unit test coverage reporting.
 
- - SetResponse
- - GetResponse
- - GetAllAlarmsNextResponse
- - MibUploadNextResponse
- - SynchronizeTimeResponse
- - AttributeValueChange
- - RebootRequest
- - RebootResponse
- - StartSoftwareDownloadRequest
- - GetNextRequest
- - GetNextResponse
- - TestResult
- - TestRequest
- - TestResponse
- - GetCurrentDataRequest
- - GetCurrentDataResponse
-
-## Message Types supported but lacking any unit test
-The following OMCI message types currently have been coded but do not
-have any unit test coverage.
-
- - StartSoftwareDownloadResponse
- - ActivateSoftwareRequest
- - ActivateSoftwareResponse
+Bug fixes will typically result in an increment of the third number in the version string
+and additional feature support will typically result in incrementing the second number. 
  
-## Message Types not yet supported
-
-The following OMCI message types currently have not been coded.
-
- - SetTableRequest
- - SetTableResponse
-
-## Extended Message Set Support
-
-As mentioned earlier, support for the Extended Message Set is underway.  Currently,
-the following Message Types have this support and are covered by unit tests:
-
- - GetRequest
- - GetResponse
- - DownloadSectionRequest/Response
- - AlarmNotification
- - AttributeValueChange
- - TestResult
-
-### Upcoming message types that will be supported
-
-The following provides a list of message types that will eventually support the _Extended Message Set_
-in the expected order of implementation.  The priority was chosen based on speed improvement requests
-of operations and ease of implementation.
-
- - GetCurrentDataRequest/Response
- - MibResetRequest/Response
- - RebootRequest/Response
- - SynchronizeTimeRequest/Response
- - CreateRequest/Response
- - DeleteRequest/Response
- - SetRequest/Response
-
- - GetNextRequest/Response
- - SetTableRequest/Response
-
- - MibUploadRequest/Response
- - MibUploadNextRequest/Response
-
- - GetAllAlarmsRequest/Response
- - GetAllAlarmsNextRequest/Response
-
- - StartSoftwareDownloadRequest/Response
- - EndSoftwareDownloadRequest/Response
- - CommitSoftwareRequest/Response
- - ActivateSoftwareRequest/Response
-  
- - TestRequest/Response
-
 ## Current user-test coverage
 
 The _**make** test_ command can be used to create code coverage support for the
-library.  The current coverage for version 1.0.0 (as of 4/21/2021) is:
+library.  The current coverage for version 2.0.0 (as of 9/08/2021) is:
 
-| File            | Statement Coverage |
-| --------------: | :---: |
-| layers.go       | 100%  |
-| mebase.go       | 91.7% |
-| meframe.go      | 50.8% |
-| messagetypes.go | 59.1% |
-| omci.go         | 79.0% |
+Entire Project:         97.3% of files and 70.2% of statements
+Generated Subdirectory: 98.5% of files and 51.9% of statements
+meframe Subdirectory:   80% of files and 55.4% of statements
+
+Main Message Directory (below):
+
+| File            | Coverage | < 75% |
+| --------------: | :------: | :---: |
+| alarms.go       |  74.3%   |   Y   |
+| avc.go          |  86%     |       |
+| create.go       |  82.5%   |       |
+| delete.go       |  85.5%   |       |
+| get.go          |  78.4%   |       |
+| getcurrent.go   |  69.4%   |       |
+| getnext.go      |  79.3%   |       |
+| layers.go       |  100%    |       |
+| mebase.go       |  93.3%   |       |
+| messagetypes.go |  100%    |       |
+| mibreset.go     |  76.6%   |       |
+| mibupload.go    |  77%     |       |
+| omci.go         |  90.6%   |       |
+| reboot.go       |  81.2%   |       |
+| set.go          |  77.3%   |       |
+| settable.go     |  81.5%   |       |
+| software.go     |  75.2%   |       |
+| synctime.go     |  79.3%   |       |
+| test.go         |  79.9%   |       |
 
 ## Other outstanding items
 
-Besides OMCI Message decode/serialization, and associated unit tests, the following items
-would be needed or useful in a first official release of this library. Some changes are
-to be done in the generated OMCI ME code as well.
+A few additional features have been requested and are listed below for future inclusion
+in the package:
 
  - Constraint checking (these are not yet fully parsed/provided by the OMCI code generated
    structs). This feature will hopefully be available in the near future.
  - Add AVC flag for appropriate attributes
- - Add some type of logging support
+ - Review other gopacket libraries for logging support and add some type of logging support
+   if it is standard. If not, recommend design patterns users of this library can use to detect
+   issues in decode or serialization.
+ - For several of the software image message types, multiple instances can be supported. Unit
+   test and source implementation to verify correct implementation is needed.
  
 Also searching through the code for _TODO_ statements will also yield additional areas of
 work to be performed.
diff --git a/VERSION b/VERSION
index 31e5c84..227cea2 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.3.3
+2.0.0
diff --git a/alarms.go b/alarms.go
new file mode 100644
index 0000000..5a5e64d
--- /dev/null
+++ b/alarms.go
@@ -0,0 +1,773 @@
+/*
+ * 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"
+	"github.com/google/gopacket"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+type GetAllAlarmsRequest struct {
+	MeBasePacket
+	AlarmRetrievalMode byte
+}
+
+func (omci *GetAllAlarmsRequest) String() string {
+	return fmt.Sprintf("%v, Retrieval Mode: %v",
+		omci.MeBasePacket.String(), omci.AlarmRetrievalMode)
+}
+
+// LayerType returns LayerTypeGetAllAlarmsRequest
+func (omci *GetAllAlarmsRequest) LayerType() gopacket.LayerType {
+	return LayerTypeGetAllAlarmsRequest
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *GetAllAlarmsRequest) CanDecode() gopacket.LayerClass {
+	return LayerTypeGetAllAlarmsRequest
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *GetAllAlarmsRequest) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		//start here
+		hdrSize = 6 + 1
+	} else {
+		hdrSize = 4 + 1
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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)
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	omci.AlarmRetrievalMode = data[4+offset]
+	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)
+}
+
+func decodeGetAllAlarmsRequestExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetAllAlarmsRequest{}
+	omci.MsgLayerType = LayerTypeGetAllAlarmsRequest
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Get All Alarms Request message
+func (omci *GetAllAlarmsRequest) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	bytes, err := b.AppendBytes(offset + 1)
+	if err != nil {
+		return err
+	}
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, uint16(1))
+	}
+	bytes[offset] = omci.AlarmRetrievalMode
+	return nil
+}
+
+type GetAllAlarmsResponse struct {
+	MeBasePacket
+	NumberOfCommands uint16
+}
+
+func (omci *GetAllAlarmsResponse) String() string {
+	return fmt.Sprintf("%v, NumberOfCommands: %d",
+		omci.MeBasePacket.String(), omci.NumberOfCommands)
+}
+
+// LayerType returns LayerTypeGetAllAlarmsResponse
+func (omci *GetAllAlarmsResponse) LayerType() gopacket.LayerType {
+	return LayerTypeGetAllAlarmsResponse
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *GetAllAlarmsResponse) CanDecode() gopacket.LayerClass {
+	return LayerTypeGetAllAlarmsResponse
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *GetAllAlarmsResponse) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		//start here
+		hdrSize = 6 + 2
+	} else {
+		hdrSize = 4 + 2
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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)
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	omci.NumberOfCommands = binary.BigEndian.Uint16(data[4+offset:])
+	return nil
+}
+
+func decodeGetAllAlarmsResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetAllAlarmsResponse{}
+	omci.MsgLayerType = LayerTypeGetAllAlarmsResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+func decodeGetAllAlarmsResponseExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetAllAlarmsResponse{}
+	omci.MsgLayerType = LayerTypeGetAllAlarmsResponse
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Get All Alarms Response message
+func (omci *GetAllAlarmsResponse) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	bytes, err := b.AppendBytes(offset + 2)
+	if err != nil {
+		return err
+	}
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, uint16(2))
+	}
+	binary.BigEndian.PutUint16(bytes[offset:], omci.NumberOfCommands)
+	return nil
+}
+
+type GetAllAlarmsNextRequest struct {
+	MeBasePacket
+	CommandSequenceNumber uint16
+}
+
+func (omci *GetAllAlarmsNextRequest) String() string {
+	return fmt.Sprintf("%v, Sequence Number: %d",
+		omci.MeBasePacket.String(), omci.CommandSequenceNumber)
+}
+
+// LayerType returns LayerTypeGetAllAlarmsNextRequest
+func (omci *GetAllAlarmsNextRequest) LayerType() gopacket.LayerType {
+	return LayerTypeGetAllAlarmsNextRequest
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *GetAllAlarmsNextRequest) CanDecode() gopacket.LayerClass {
+	return LayerTypeGetAllAlarmsNextRequest
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *GetAllAlarmsNextRequest) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		//start here
+		hdrSize = 6 + 2
+	} else {
+		hdrSize = 4 + 2
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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)
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	omci.CommandSequenceNumber = binary.BigEndian.Uint16(data[4+offset:])
+	return nil
+}
+
+func decodeGetAllAlarmsNextRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetAllAlarmsNextRequest{}
+	omci.MsgLayerType = LayerTypeGetAllAlarmsNextRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+func decodeGetAllAlarmsNextRequestExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetAllAlarmsNextRequest{}
+	omci.MsgLayerType = LayerTypeGetAllAlarmsNextRequest
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Get All Alarms Next Request message
+func (omci *GetAllAlarmsNextRequest) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	bytes, err := b.AppendBytes(offset + 2)
+	if err != nil {
+		return err
+	}
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, uint16(2))
+	}
+	binary.BigEndian.PutUint16(bytes[offset:], omci.CommandSequenceNumber)
+	return nil
+}
+
+type AdditionalAlarmsData struct {
+	AlarmEntityClass    me.ClassID
+	AlarmEntityInstance uint16
+	AlarmBitMap         [28]byte // 224 bits
+}
+
+type GetAllAlarmsNextResponse struct {
+	MeBasePacket
+	AlarmEntityClass    me.ClassID
+	AlarmEntityInstance uint16
+	AlarmBitMap         [28]byte               // 224 bits
+	AdditionalAlarms    []AdditionalAlarmsData // Valid only for extended message set version
+}
+
+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)
+}
+
+// LayerType returns LayerTypeGetAllAlarmsNextResponse
+func (omci *GetAllAlarmsNextResponse) LayerType() gopacket.LayerType {
+	return LayerTypeGetAllAlarmsNextResponse
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *GetAllAlarmsNextResponse) CanDecode() gopacket.LayerClass {
+	return LayerTypeGetAllAlarmsNextResponse
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *GetAllAlarmsNextResponse) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6
+	} else {
+		hdrSize = 4
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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)
+	}
+	//err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+4+28)	// 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.
+	var offset int
+	msgContentsLen := 28
+	if omci.Extended {
+		offset = 2 // Message Contents length (2)
+		msgContentsLen = int(binary.BigEndian.Uint16(data[6:]))
+	}
+	if len(data[4+offset:]) < 4+msgContentsLen {
+		p.SetTruncated()
+		return errors.New("frame too small: Get All Alarms Next Response Managed Entity attribute truncated")
+	}
+	omci.AlarmEntityClass = me.ClassID(binary.BigEndian.Uint16(data[4+offset:]))
+	omci.AlarmEntityInstance = binary.BigEndian.Uint16(data[6+offset:])
+
+	copy(omci.AlarmBitMap[:], data[8+offset:36])
+	remaining := len(data) - (6 + 4 + 28)
+
+	if !omci.Extended || remaining <= 0 {
+		return nil
+	}
+	offset = 6 + 4 + 28
+	omci.AdditionalAlarms = make([]AdditionalAlarmsData, 0)
+	for remaining > 0 {
+		if remaining < 4+28 {
+			p.SetTruncated()
+			return errors.New("frame too small: Get All Alarms Next Response Managed Entity attribute truncated")
+		}
+		alarm := AdditionalAlarmsData{
+			AlarmEntityClass:    me.ClassID(binary.BigEndian.Uint16(data[offset:])),
+			AlarmEntityInstance: binary.BigEndian.Uint16(data[offset+2:]),
+		}
+		copy(alarm.AlarmBitMap[:], data[offset+4:])
+		omci.AdditionalAlarms = append(omci.AdditionalAlarms, alarm)
+
+		offset += 4 + 28
+		remaining -= 4 + 28
+	}
+	return nil
+}
+
+func decodeGetAllAlarmsNextResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetAllAlarmsNextResponse{}
+	omci.MsgLayerType = LayerTypeGetAllAlarmsNextResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+func decodeGetAllAlarmsNextResponseExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetAllAlarmsNextResponse{}
+	omci.MsgLayerType = LayerTypeGetAllAlarmsNextResponse
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Get All Alarms Next Response message
+func (omci *GetAllAlarmsNextResponse) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	contentLength := 2 + 2 + 28
+	maxLength := MaxBaselineLength - 8 - 8
+	var extraMEs int
+	var offset int
+
+	if omci.Extended {
+		maxLength = MaxExtendedLength - 10 - 4
+		offset = 2
+		contentLength += 2 // Length field
+		if omci.AdditionalAlarms != nil {
+			extraMEs = len(omci.AdditionalAlarms)
+			contentLength += extraMEs*4 + 28
+		}
+	}
+	if contentLength > maxLength {
+		msg := fmt.Sprintf("not enough space to fit all requested Managed Entities, have %v, requested: %v",
+			maxLength, contentLength)
+		return me.NewMessageTruncatedError(msg)
+	}
+	// Allocate space for all
+	bytes, err := b.AppendBytes(contentLength)
+	if err != nil {
+		return err
+	}
+	// Always encode the first ME alarm data
+	binary.BigEndian.PutUint16(bytes[offset:], uint16(omci.AlarmEntityClass))
+	binary.BigEndian.PutUint16(bytes[offset+2:], omci.AlarmEntityInstance)
+	copy(bytes[offset+4:], omci.AlarmBitMap[:])
+
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, uint16(contentLength-2))
+
+		if omci.AdditionalAlarms != nil {
+			for index, value := range omci.AdditionalAlarms {
+				offset = (32 * (index + 1)) + 2
+				binary.BigEndian.PutUint16(bytes[offset:], uint16(value.AlarmEntityClass))
+				binary.BigEndian.PutUint16(bytes[offset+2:], value.AlarmEntityInstance)
+				copy(bytes[offset+4:], value.AlarmBitMap[:])
+			}
+		}
+	}
+	return nil
+}
+
+const AlarmBitmapSize = 224
+
+type AlarmNotificationMsg struct {
+	MeBasePacket
+	AlarmBitmap         [AlarmBitmapSize / 8]byte
+	zeroPadding         [3]byte // Note: This zero padding is not present in the Extended Message Set
+	AlarmSequenceNumber byte
+}
+
+func (omci *AlarmNotificationMsg) String() string {
+	return fmt.Sprintf("%v, Sequence Number: %d, Alarm Bitmap: %v",
+		omci.MeBasePacket.String(), omci.AlarmSequenceNumber, omci.AlarmBitmap)
+}
+
+// LayerType returns LayerTypeAlarmNotification
+func (omci *AlarmNotificationMsg) LayerType() gopacket.LayerType {
+	return LayerTypeAlarmNotification
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *AlarmNotificationMsg) CanDecode() gopacket.LayerClass {
+	return LayerTypeAlarmNotification
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *AlarmNotificationMsg) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+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)
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return false, omciErr.GetError()
+	}
+	alarmMap := entity.GetAlarmMap()
+	if alarmMap == nil {
+		msg := "managed entity does not support Alarm notifications"
+		return false, errors.New(msg)
+	}
+	if _, ok := alarmMap[alarmNumber]; !ok {
+		msg := fmt.Sprintf("unsupported invalid alarm number: %v", 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)
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return false, omciErr.GetError()
+	}
+	alarmMap := entity.GetAlarmMap()
+	if alarmMap == nil {
+		return false, errors.New("managed entity does not support Alarm notifications")
+	}
+	if _, ok := alarmMap[alarmNumber]; !ok {
+		msg := fmt.Sprintf("unsupported invalid alarm number: %v", 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)
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	alarmMap := entity.GetAlarmMap()
+	if alarmMap == nil {
+		return errors.New("managed entity does not support Alarm notifications")
+	}
+	if _, ok := alarmMap[alarmNumber]; !ok {
+		msg := fmt.Sprintf("unsupported invalid alarm number: %v", 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)
+	}
+	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	alarmMap := entity.GetAlarmMap()
+	if alarmMap == nil {
+		return errors.New("managed entity does not support Alarm notifications")
+	}
+	if _, ok := alarmMap[alarmNumber]; !ok {
+		msg := fmt.Sprintf("unsupported invalid alarm number: %v", 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, 4+28)
+	if err != nil {
+		return err
+	}
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+		me.ParamData{EntityID: omci.EntityInstance})
+	if omciErr.StatusCode() != me.Success {
+		return omciErr.GetError()
+	}
+	// Is this an unsupported or vendor specific ME.  If so, it is not an error to decode
+	// the alarms.  We just cannot provide any alarm names.  Handle decode here.
+	classSupport := meDefinition.GetClassSupport()
+	isUnsupported := classSupport == me.UnsupportedManagedEntity ||
+		classSupport == me.UnsupportedVendorSpecificManagedEntity
+
+	mapOffset := 4
+	if omci.Extended {
+		mapOffset = 6
+		if len(data) < 6+28+1 {
+			p.SetTruncated()
+			return errors.New("frame too small")
+		}
+	}
+	// Look for a non-nil/not empty Alarm Map to determine if this ME supports alarms
+	if alarmMap := meDefinition.GetAlarmMap(); isUnsupported || (alarmMap != nil && len(alarmMap) > 0) {
+		for index, octet := range data[mapOffset : (AlarmBitmapSize/8)-mapOffset] {
+			omci.AlarmBitmap[index] = octet
+		}
+		if omci.Extended {
+			omci.AlarmSequenceNumber = data[mapOffset+(AlarmBitmapSize/8)]
+		} else {
+			padOffset := mapOffset + (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
+	}
+	return me.NewProcessingError("managed entity does not support alarm notifications")
+}
+
+func decodeAlarmNotification(data []byte, p gopacket.PacketBuilder) error {
+	omci := &AlarmNotificationMsg{}
+	omci.MsgLayerType = LayerTypeAlarmNotification
+	return decodingLayerDecoder(omci, data, p)
+}
+
+func decodeAlarmNotificationExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &AlarmNotificationMsg{}
+	omci.MsgLayerType = LayerTypeAlarmNotification
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Alarm Notification message
+func (omci *AlarmNotificationMsg) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	// TODO: Support of encoding AlarmNotification into supported types not yet supported
+	//meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
+	//	me.ParamData{EntityID: omci.EntityInstance})
+	//if omciErr.StatusCode() != me.Success {
+	//	return omciErr.GetError()
+	//}
+	//if !me.SupportsMsgType(meDefinition, me.AlarmNotification) {
+	//	return me.NewProcessingError("managed entity does not support Alarm Notification Message-Type")
+	//}
+	if omci.Extended {
+		bytes, err := b.AppendBytes(2 + (AlarmBitmapSize / 8) + 1)
+		if err != nil {
+			return err
+		}
+		binary.BigEndian.PutUint16(bytes, uint16((AlarmBitmapSize/8)+1))
+
+		for index, octet := range omci.AlarmBitmap {
+			bytes[2+index] = octet
+		}
+		bytes[2+(AlarmBitmapSize/8)] = omci.AlarmSequenceNumber
+	} else {
+		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
+}
diff --git a/alarms_test.go b/alarms_test.go
new file mode 100644
index 0000000..c1f4e45
--- /dev/null
+++ b/alarms_test.go
@@ -0,0 +1,1072 @@
+/*
+ * 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_test
+
+import (
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/stretchr/testify/assert"
+	"strings"
+	"testing"
+)
+
+func TestGetAllAlarmsRequestDecode(t *testing.T) {
+	goodMessage := "04454b0a00020000000000000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeGetAllAlarmsRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0445), omciMsg.TransactionID)
+	assert.Equal(t, GetAllAlarmsRequestType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeGetAllAlarmsRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*GetAllAlarmsRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeGetAllAlarmsRequest, request.LayerType())
+	assert.Equal(t, LayerTypeGetAllAlarmsRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, byte(0), request.AlarmRetrievalMode)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestGetAllAlarmsRequestDecodeExtended(t *testing.T) {
+	goodMessage := "04454b0b00020000000101"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeGetAllAlarmsRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0445), omciMsg.TransactionID)
+	assert.Equal(t, GetAllAlarmsRequestType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(1), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeGetAllAlarmsRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*GetAllAlarmsRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeGetAllAlarmsRequest, request.LayerType())
+	assert.Equal(t, LayerTypeGetAllAlarmsRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, byte(1), request.AlarmRetrievalMode)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestGetAllAlarmsRequestSerialize(t *testing.T) {
+	goodMessage := "04454b0a00020000010000000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x0445,
+		MessageType:   GetAllAlarmsRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &GetAllAlarmsRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+		},
+		AlarmRetrievalMode: byte(1),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestGetAllAlarmsRequestSerializeExtended(t *testing.T) {
+	goodMessage := "04454b0b00020000000101"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0445,
+		MessageType:      GetAllAlarmsRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &GetAllAlarmsRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+			Extended:       true,
+		},
+		AlarmRetrievalMode: byte(1),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestGetAllAlarmsResponseDecode(t *testing.T) {
+	goodMessage := "04452b0a00020000000300000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeGetAllAlarmsResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0445), omciMsg.TransactionID)
+	assert.Equal(t, GetAllAlarmsResponseType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeGetAllAlarmsResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*GetAllAlarmsResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeGetAllAlarmsResponse, response.LayerType())
+	assert.Equal(t, LayerTypeGetAllAlarmsResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, uint16(3), response.NumberOfCommands)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestGetAllAlarmsResponseDecodeExtended(t *testing.T) {
+	goodMessage := "04452b0b0002000000020003"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeGetAllAlarmsResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0445), omciMsg.TransactionID)
+	assert.Equal(t, GetAllAlarmsResponseType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(2), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeGetAllAlarmsResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*GetAllAlarmsResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeGetAllAlarmsResponse, response.LayerType())
+	assert.Equal(t, LayerTypeGetAllAlarmsResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, uint16(3), response.NumberOfCommands)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestGetAllAlarmsResponseSerialize(t *testing.T) {
+	goodMessage := "04452b0a00020000000300000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x0445,
+		MessageType:   GetAllAlarmsResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &GetAllAlarmsResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+		},
+		NumberOfCommands: uint16(3),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestGetAllAlarmsResponseSerializeExtended(t *testing.T) {
+	goodMessage := "04452b0b0002000000020003"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0445,
+		MessageType:      GetAllAlarmsResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &GetAllAlarmsResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+			Extended:       true,
+		},
+		NumberOfCommands: uint16(3),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestGetAllAlarmsNextRequestDecode(t *testing.T) {
+	goodMessage := "02344c0a00020000000300000000000000000000000000000000000000000000000000000000000000000028"
+
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeGetAllAlarmsNextRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0234), omciMsg.TransactionID)
+	assert.Equal(t, GetAllAlarmsNextRequestType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeGetAllAlarmsNextRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*GetAllAlarmsNextRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeGetAllAlarmsNextRequest, request.LayerType())
+	assert.Equal(t, LayerTypeGetAllAlarmsNextRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, uint16(3), request.CommandSequenceNumber)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestGetAllAlarmsNextRequestDecodeExtended(t *testing.T) {
+	goodMessage := "02344c0b0002000000020003"
+
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeGetAllAlarmsNextRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0234), omciMsg.TransactionID)
+	assert.Equal(t, GetAllAlarmsNextRequestType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(2), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeGetAllAlarmsNextRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*GetAllAlarmsNextRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeGetAllAlarmsNextRequest, request.LayerType())
+	assert.Equal(t, LayerTypeGetAllAlarmsNextRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, uint16(3), request.CommandSequenceNumber)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestGetAllAlarmsNextRequestSerialize(t *testing.T) {
+	goodMessage := "02344c0a00020000000300000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x0234,
+		MessageType:   GetAllAlarmsNextRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &GetAllAlarmsNextRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+		},
+		CommandSequenceNumber: uint16(3),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestGetAllAlarmsNextRequestSerializeExtended(t *testing.T) {
+	goodMessage := "02344c0b0002000000020004"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0234,
+		MessageType:      GetAllAlarmsNextRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &GetAllAlarmsNextRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+			Extended:       true,
+		},
+		CommandSequenceNumber: uint16(4),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestGetAllAlarmsNextResponseDecode(t *testing.T) {
+	goodMessage := "02342c0a00020000000b01028000000000000000000000000000000000000000000000000000000000000028f040fc87"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeGetAllAlarmsNextResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0234), omciMsg.TransactionID)
+	assert.Equal(t, GetAllAlarmsNextResponseType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeGetAllAlarmsNextResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*GetAllAlarmsNextResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeGetAllAlarmsNextResponse, response.LayerType())
+	assert.Equal(t, LayerTypeGetAllAlarmsNextResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+
+	var alarms [224 / 8]byte
+	alarms[0] = 0x80
+	assert.Equal(t, me.PhysicalPathTerminationPointEthernetUniClassID, response.AlarmEntityClass)
+	assert.Equal(t, uint16(0x102), response.AlarmEntityInstance)
+	assert.Equal(t, alarms, response.AlarmBitMap)
+	assert.Nil(t, response.AdditionalAlarms)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestGetAllAlarmsNextResponseDecodeExtended(t *testing.T) {
+	goodMessage := "02342c0b000200000020000b010280000000000000000000000000000000000000000000000000000000"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeGetAllAlarmsNextResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0234), omciMsg.TransactionID)
+	assert.Equal(t, GetAllAlarmsNextResponseType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(32), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeGetAllAlarmsNextResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*GetAllAlarmsNextResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeGetAllAlarmsNextResponse, response.LayerType())
+	assert.Equal(t, LayerTypeGetAllAlarmsNextResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+
+	var alarms [224 / 8]byte
+	alarms[0] = 0x80
+	assert.Equal(t, me.PhysicalPathTerminationPointEthernetUniClassID, response.AlarmEntityClass)
+	assert.Equal(t, uint16(0x102), response.AlarmEntityInstance)
+	assert.Equal(t, alarms, response.AlarmBitMap)
+	assert.Nil(t, response.AdditionalAlarms)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestGetAllAlarmsNextResponseDecodeExtendedTwoBitmaps(t *testing.T) {
+	alarm1 := "000b010280000000000000000000000000000000000000000000000000000000"
+	alarm2 := "000b010380000000000000000000000000000000000000000000000000000000"
+	goodMessage := "02342c0b000200000040" + alarm1 + alarm2
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeGetAllAlarmsNextResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0234), omciMsg.TransactionID)
+	assert.Equal(t, GetAllAlarmsNextResponseType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(64), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeGetAllAlarmsNextResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*GetAllAlarmsNextResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeGetAllAlarmsNextResponse, response.LayerType())
+	assert.Equal(t, LayerTypeGetAllAlarmsNextResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+
+	var alarms [224 / 8]byte
+	alarms[0] = 0x80
+	assert.Equal(t, me.PhysicalPathTerminationPointEthernetUniClassID, response.AlarmEntityClass)
+	assert.Equal(t, uint16(0x102), response.AlarmEntityInstance)
+	assert.Equal(t, alarms, response.AlarmBitMap)
+
+	assert.NotNil(t, response.AdditionalAlarms)
+	assert.Equal(t, 1, len(response.AdditionalAlarms))
+	assert.Equal(t, me.PhysicalPathTerminationPointEthernetUniClassID, response.AdditionalAlarms[0].AlarmEntityClass)
+	assert.Equal(t, uint16(0x103), response.AdditionalAlarms[0].AlarmEntityInstance)
+	assert.Equal(t, alarms, response.AdditionalAlarms[0].AlarmBitMap)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestGetAllAlarmsNextResponseSerialize(t *testing.T) {
+	goodMessage := "02342c0a00020000000b01028000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x0234,
+		MessageType:   GetAllAlarmsNextResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	var alarms [224 / 8]byte
+	alarms[0] = 0x80
+
+	request := &GetAllAlarmsNextResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+		},
+		AlarmEntityClass:    me.PhysicalPathTerminationPointEthernetUniClassID,
+		AlarmEntityInstance: uint16(0x102),
+		AlarmBitMap:         alarms,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestGetAllAlarmsNextResponseSerializeExtended(t *testing.T) {
+	goodMessage := "02342c0b000200000020000b010280000000000000000000000000000000000000000000000000000000"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0234,
+		MessageType:      GetAllAlarmsNextResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	var alarms [224 / 8]byte
+	alarms[0] = 0x80
+
+	request := &GetAllAlarmsNextResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+			Extended:       true,
+		},
+		AlarmEntityClass:    me.PhysicalPathTerminationPointEthernetUniClassID,
+		AlarmEntityInstance: uint16(0x102),
+		AlarmBitMap:         alarms,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestGetAllAlarmsNextResponseSerializeExtendedTwoBitmaps(t *testing.T) {
+	alarm1 := "000b010280000000000000000000000000000000000000000000000000000000"
+	alarm2 := "000b010380000000000000000000000000000000000000000000000000000000"
+	goodMessage := "02342c0b000200000040" + alarm1 + alarm2
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0234,
+		MessageType:      GetAllAlarmsNextResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	var alarms [224 / 8]byte
+	alarms[0] = 0x80
+
+	secondAlarm := AdditionalAlarmsData{
+		AlarmEntityClass:    me.PhysicalPathTerminationPointEthernetUniClassID,
+		AlarmEntityInstance: uint16(0x103),
+		AlarmBitMap:         alarms,
+	}
+	request := &GetAllAlarmsNextResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+			Extended:       true,
+		},
+		AlarmEntityClass:    me.PhysicalPathTerminationPointEthernetUniClassID,
+		AlarmEntityInstance: uint16(0x102),
+		AlarmBitMap:         alarms,
+		AdditionalAlarms:    []AdditionalAlarmsData{secondAlarm},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestGetAllAlarmsNextResponseBadCommandNumberDecode(t *testing.T) {
+	// Test of a GetNext Response that results when an invalid command number
+	// is requested. In the case where the ONU receives a get all alarms next
+	// request message in which the command sequence number is out of range,
+	// the ONU should respond with a message in which bytes 9 to 40 are all
+	// set to 0. This corresponds to a response with entity class 0, entity
+	// instance 0, and bit map all 0s.
+	//TODO: Implement
+}
+
+func TestGetAllAlarmsNextResponseBadCommandNumberSerialize(t *testing.T) {
+	// Test of a GetNext Response that results when an invalid command number
+	// is requested.
+	//TODO: Implement
+}
+
+func TestAlarmNotificationDecode(t *testing.T) {
+	goodMessage := "0000100a000b0104800000000000000000000000000000000000000000000000000000000000000500000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, uint16(0x0), omciMsg.TransactionID)
+	assert.Equal(t, AlarmNotificationType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeAlarmNotification)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*AlarmNotificationMsg)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeAlarmNotification, request.LayerType())
+	assert.Equal(t, LayerTypeAlarmNotification, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, me.PhysicalPathTerminationPointEthernetUniClassID, request.EntityClass)
+	assert.Equal(t, uint16(0x104), request.EntityInstance)
+	assert.Equal(t, [28]byte{
+		0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	}, request.AlarmBitmap)
+	assert.Equal(t, byte(5), request.AlarmSequenceNumber)
+
+	// Active/Clear tests
+	active, err2 := request.IsAlarmActive(0)
+	clear, err3 := request.IsAlarmClear(0)
+	assert.Nil(t, err2)
+	assert.Nil(t, err3)
+	assert.True(t, active)
+	assert.False(t, clear)
+
+	// Active/Clear for undefined alarm bits
+	active, err2 = request.IsAlarmActive(1)
+	clear, err3 = request.IsAlarmClear(1)
+	assert.NotNil(t, err2)
+	assert.NotNil(t, err3)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestInvalidClassAlarmNotificationDecode(t *testing.T) {
+	// Choosing GalEthernetProfile (272) since it does not support alarms, show we should
+	// file the decode
+	badMessage := "0000100a01100104800000000000000000000000000000000000000000000000000000000000000500000028"
+	data, err := stringToPacket(badMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeAlarmNotification, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0), omciMsg.TransactionID)
+	assert.Equal(t, AlarmNotificationType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeAlarmNotification)
+	assert.Nil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*AlarmNotificationMsg)
+	assert.False(t, ok2)
+	assert.Nil(t, request)
+	assert.Equal(t, LayerTypeAlarmNotification, request.LayerType())
+	assert.Equal(t, LayerTypeAlarmNotification, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+}
+
+func TestUnknownsMeAlarmNotificationDecode(t *testing.T) {
+	// Choosing class ID 22 since it is in the G.988 class ID space and is reserved
+	goodMessage := "0000100a00160104800000000000000000000000000000000000000000000000000000000000000500000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeAlarmNotification, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0), omciMsg.TransactionID)
+	assert.Equal(t, AlarmNotificationType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeAlarmNotification)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*AlarmNotificationMsg)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeAlarmNotification, request.LayerType())
+	assert.Equal(t, LayerTypeAlarmNotification, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, me.ClassID(22), request.EntityClass)
+	assert.Equal(t, uint16(0x104), request.EntityInstance)
+	assert.Equal(t, [28]byte{
+		0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	}, request.AlarmBitmap)
+	assert.Equal(t, byte(5), request.AlarmSequenceNumber)
+}
+
+func TestVendorSpecificAlarmNotificationDecode(t *testing.T) {
+	// Choosing class ID 255 since it is in the first vendor specific class ID space
+	goodMessage := "0000100a00FF0104800000000000000000000000000000000000000000000000000000000000000500000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeAlarmNotification, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0), omciMsg.TransactionID)
+	assert.Equal(t, AlarmNotificationType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeAlarmNotification)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*AlarmNotificationMsg)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeAlarmNotification, request.LayerType())
+	assert.Equal(t, LayerTypeAlarmNotification, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, me.ClassID(255), request.EntityClass)
+	assert.Equal(t, uint16(0x104), request.EntityInstance)
+	assert.Equal(t, [28]byte{
+		0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	}, request.AlarmBitmap)
+	assert.Equal(t, byte(5), request.AlarmSequenceNumber)
+}
+
+func TestAlarmNotificationSerialize(t *testing.T) {
+	goodMessage := "0000100a000b0104800000000000000000000000000000000000000000000000000000000000000500000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0,
+		MessageType:   AlarmNotificationType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &AlarmNotificationMsg{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.PhysicalPathTerminationPointEthernetUniClassID,
+			EntityInstance: uint16(0x104),
+		},
+		AlarmBitmap: [28]byte{
+			0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		},
+		AlarmSequenceNumber: byte(5),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestAlarmNotificationSerializeNonZeroTIC(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 1,
+		MessageType:   AlarmNotificationType,
+	}
+	request := &AlarmNotificationMsg{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.PhysicalPathTerminationPointEthernetUniClassID,
+			EntityInstance: uint16(0x104),
+		},
+		AlarmBitmap: [28]byte{
+			0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		},
+		AlarmSequenceNumber: byte(5),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestExtendedAlarmNotificationDecode(t *testing.T) {
+	//                                   1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8
+	goodMessage := "0000100b000b0104001d8000000000000000000000000000000000000000000000000000000005"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeAlarmNotification, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0), omciMsg.TransactionID)
+	assert.Equal(t, AlarmNotificationType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(29), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeAlarmNotification)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*AlarmNotificationMsg)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeAlarmNotification, request.LayerType())
+	assert.Equal(t, LayerTypeAlarmNotification, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, me.PhysicalPathTerminationPointEthernetUniClassID, request.EntityClass)
+	assert.Equal(t, uint16(0x104), request.EntityInstance)
+	assert.Equal(t, [28]byte{
+		0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	}, request.AlarmBitmap)
+	assert.Equal(t, byte(5), request.AlarmSequenceNumber)
+
+	// Active/Clear tests
+	active, err2 := request.IsAlarmActive(0)
+	clear, err3 := request.IsAlarmClear(0)
+	assert.Nil(t, err2)
+	assert.Nil(t, err3)
+	assert.True(t, active)
+	assert.False(t, clear)
+
+	// Active/Clear for undefined alarm bits
+	active, err2 = request.IsAlarmActive(1)
+	clear, err3 = request.IsAlarmClear(1)
+	assert.NotNil(t, err2)
+	assert.NotNil(t, err3)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedAlarmNotificationSerialize(t *testing.T) {
+	//                                   1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8
+	goodMessage := "0000100b000b0104001d8000000000000000000000000000000000000000000000000000000005"
+
+	omciLayer := &OMCI{
+		TransactionID:    0,
+		MessageType:      AlarmNotificationType,
+		DeviceIdentifier: ExtendedIdent,
+		// Length parameter is optional for Extended message format serialization
+		// and if present it will be overwritten during the serialization with the
+		// actual value.
+	}
+	request := &AlarmNotificationMsg{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.PhysicalPathTerminationPointEthernetUniClassID,
+			EntityInstance: uint16(0x104),
+			Extended:       true,
+		},
+		AlarmBitmap: [28]byte{
+			0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		},
+		AlarmSequenceNumber: byte(5),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestAlarmDecodesOmciLayerHeaderTooSmall(t *testing.T) {
+	// Baseline is always checked for < 40 octets and that test is in mebase_test.go. And
+	// that test also handles Extended message set where the length field is short. This
+	// test for a valid length field but no message content past that.
+	getAllAlarmsRequestExt := "04454b0b000200000000"
+	getAllAlarmsResponseExt := "04452b0b000200000000"
+	getAllAlarmsNextRequestExt := "02344c0b000200000000"
+	alarmNotificationExt := "0000100b000b01040000"
+
+	frames := []string{
+		getAllAlarmsRequestExt,
+		getAllAlarmsResponseExt,
+		getAllAlarmsNextRequestExt,
+		alarmNotificationExt,
+	}
+	for _, frame := range frames {
+		data, err := stringToPacket(frame)
+		assert.NoError(t, err)
+
+		// Should get packet but with error layer
+		packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+		assert.NotNil(t, packet)
+
+		// OMCI layer should be present (but not message type specific layer)
+		omciLayer := packet.Layer(LayerTypeOMCI)
+		assert.NotNil(t, omciLayer)
+
+		// And there is an error layer. Since OMCI, we only have two OMCI and
+		// the message type layer (which should be the failed one)
+		assert.Equal(t, 2, len(packet.Layers()))
+		errLayer := packet.ErrorLayer()
+		assert.NotNil(t, errLayer)
+		metaData := packet.Metadata()
+		assert.NotNil(t, metaData)
+		assert.True(t, metaData.Truncated)
+	}
+}
diff --git a/avc.go b/avc.go
new file mode 100644
index 0000000..5242e3b
--- /dev/null
+++ b/avc.go
@@ -0,0 +1,160 @@
+/*
+ * 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"
+	"fmt"
+	"github.com/google/gopacket"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+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)
+}
+
+// LayerType returns LayerTypeAttributeValueChange
+func (omci *AttributeValueChangeMsg) LayerType() gopacket.LayerType {
+	return LayerTypeAttributeValueChange
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *AttributeValueChangeMsg) CanDecode() gopacket.LayerClass {
+	return LayerTypeAttributeValueChange
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *AttributeValueChangeMsg) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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, 4+2)
+	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: Support for encoding AVC into message type support not yet supported
+	//if !me.SupportsMsgType(meDefinition, me.AlarmNotification) {
+	//	return me.NewProcessingError("managed entity does not support Alarm Notification Message-Type")
+	//}
+	maskOffset := 4
+	if omci.Extended {
+		maskOffset = 6
+	}
+	omci.AttributeMask = binary.BigEndian.Uint16(data[maskOffset:])
+	// Attribute decode
+	omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask, data[maskOffset+2:],
+		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)
+}
+
+func decodeAttributeValueChangeExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &AttributeValueChangeMsg{}
+	omci.MsgLayerType = LayerTypeAttributeValueChange
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Attribute Value Change Notification message
+func (omci *AttributeValueChangeMsg) SerializeTo(b gopacket.SerializeBuffer, _ 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)
+	//	}
+	//}
+	var maskOffset int
+	var bytesAvailable int
+	if omci.Extended {
+		maskOffset = 2
+		bytesAvailable = MaxExtendedLength - 12 - 4
+	} else {
+		maskOffset = 0
+		bytesAvailable = MaxBaselineLength - 10 - 8
+	}
+	bytes, err := b.AppendBytes(maskOffset + 2)
+	if err != nil {
+		return err
+	}
+	binary.BigEndian.PutUint16(bytes[maskOffset:], omci.AttributeMask)
+
+	// Attribute serialization
+	attributeBuffer := gopacket.NewSerializeBuffer()
+	if err, _ = meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask,
+		attributeBuffer, byte(GetResponseType), bytesAvailable, false); err != nil {
+		return err
+	}
+
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, uint16(len(attributeBuffer.Bytes())+2))
+	}
+	bytes, err = b.AppendBytes(len(attributeBuffer.Bytes()))
+	if err != nil {
+		return err
+	}
+	copy(bytes, attributeBuffer.Bytes())
+	return nil
+}
diff --git a/avc_test.go b/avc_test.go
new file mode 100644
index 0000000..3346a10
--- /dev/null
+++ b/avc_test.go
@@ -0,0 +1,215 @@
+/*
+ * 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_test
+
+import (
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/stretchr/testify/assert"
+	"strings"
+	"testing"
+)
+
+func TestAttributeValueChangeDecode(t *testing.T) {
+	goodMessage := "0000110a0007000080004d4c2d33363236000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeAttributeValueChange, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0), omciMsg.TransactionID)
+	assert.Equal(t, AttributeValueChangeType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeAttributeValueChange)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*AttributeValueChangeMsg)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeAttributeValueChange, request.LayerType())
+	assert.Equal(t, LayerTypeAttributeValueChange, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, uint16(0x8000), request.AttributeMask)
+	assert.Equal(t, me.SoftwareImageClassID, request.EntityClass)
+	assert.Equal(t, uint16(0), request.EntityInstance)
+	assert.Equal(t, []byte{
+		0x4d, 0x4c, 0x2d, 0x33, 0x36, 0x32, 0x36,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		request.Attributes["Version"])
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestAttributeValueChangeSerialize(t *testing.T) {
+	goodMessage := "0000110a0007000080004d4c2d33363236000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0,
+		MessageType:   AttributeValueChangeType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &AttributeValueChangeMsg{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: uint16(0),
+		},
+		AttributeMask: uint16(0x8000),
+		Attributes: me.AttributeValueMap{
+			"Version": []byte{
+				0x4d, 0x4c, 0x2d, 0x33, 0x36, 0x32, 0x36,
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			},
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestAttributeValueChangeNonZeroTicSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 1,
+		MessageType:   AttributeValueChangeType,
+	}
+	request := &AttributeValueChangeMsg{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: uint16(0),
+		},
+		AttributeMask: uint16(0x8000),
+		Attributes: me.AttributeValueMap{
+			"Version": []byte{
+				0x4d, 0x4c, 0x2d, 0x33, 0x36, 0x32, 0x36,
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			},
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestExtendedAttributeValueChangeDecode(t *testing.T) {
+	// Software Image Version (14 bytes) AVC
+	goodMessage := "0000110b00070000001080004d4c2d3336323600000000000000"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeAttributeValueChange, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0), omciMsg.TransactionID)
+	assert.Equal(t, AttributeValueChangeType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(2+14), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeAttributeValueChange)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*AttributeValueChangeMsg)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeAttributeValueChange, request.LayerType())
+	assert.Equal(t, LayerTypeAttributeValueChange, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, uint16(0x8000), request.AttributeMask)
+	assert.Equal(t, me.SoftwareImageClassID, request.EntityClass)
+	assert.Equal(t, uint16(0), request.EntityInstance)
+	assert.Equal(t, []byte{
+		0x4d, 0x4c, 0x2d, 0x33, 0x36, 0x32, 0x36,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, request.Attributes["Version"])
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedAttributeValueChangeSerialize(t *testing.T) {
+	goodMessage := "0000110b00070000001080004d4c2d3336323600000000000000"
+
+	omciLayer := &OMCI{
+		TransactionID:    0,
+		MessageType:      AttributeValueChangeType,
+		DeviceIdentifier: ExtendedIdent,
+		// Length parameter is optional for Extended message format serialization
+		// and if present it will be overwritten during the serialization with the
+		// actual value.
+	}
+	request := &AttributeValueChangeMsg{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: uint16(0),
+			Extended:       true,
+		},
+		AttributeMask: uint16(0x8000),
+		Attributes: me.AttributeValueMap{
+			"Version": []byte{
+				0x4d, 0x4c, 0x2d, 0x33, 0x36, 0x32, 0x36,
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			},
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
diff --git a/create.go b/create.go
new file mode 100644
index 0000000..4f7519f
--- /dev/null
+++ b/create.go
@@ -0,0 +1,273 @@
+/*
+ * 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"
+	"github.com/google/gopacket"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+// CreateRequest message apply only to attributes that are defined to be set by create.
+// Writeable attributes that are not set by create are not permitted in a create message
+type CreateRequest struct {
+	MeBasePacket
+	Attributes me.AttributeValueMap
+}
+
+func (omci *CreateRequest) String() string {
+	return fmt.Sprintf("%v, attributes: %v", omci.MeBasePacket.String(), omci.Attributes)
+}
+
+// LayerType returns LayerTypeCreateRequest
+func (omci *CreateRequest) LayerType() gopacket.LayerType {
+	return LayerTypeCreateRequest
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *CreateRequest) CanDecode() gopacket.LayerClass {
+	return LayerTypeCreateRequest
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *CreateRequest) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6
+	} else {
+		hdrSize = 4
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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[hdrSize:], p, byte(CreateRequestType))
+	if err != nil {
+		return err
+	}
+	if eidDef, eidDefOK := meDefinition.GetAttributeDefinitions()[0]; eidDefOK {
+		omci.Attributes[eidDef.GetName()] = omci.EntityInstance
+		return nil
+	}
+	return me.NewProcessingError("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)
+}
+
+func decodeCreateRequestExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &CreateRequest{}
+	omci.MsgLayerType = LayerTypeCreateRequest
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Create Request Message
+func (omci *CreateRequest) SerializeTo(b gopacket.SerializeBuffer, _ 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
+	var bytesAvailable int
+	var bytes []byte
+	if omci.Extended {
+		bytesAvailable = MaxExtendedLength - 10 - 4
+		bytes, err = b.AppendBytes(2)
+		if err != nil {
+			return err
+		}
+	} else {
+		bytesAvailable = MaxBaselineLength - 8 - 8
+	}
+	attributeBuffer := gopacket.NewSerializeBuffer()
+	if err, _ = meDefinition.SerializeAttributes(omci.Attributes, sbcMask,
+		attributeBuffer, byte(CreateRequestType), bytesAvailable, false); err != nil {
+		return err
+	}
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, uint16(len(attributeBuffer.Bytes())))
+	}
+	bytes, err = b.AppendBytes(len(attributeBuffer.Bytes()))
+	if err != nil {
+		return err
+	}
+	copy(bytes, attributeBuffer.Bytes())
+	return nil
+}
+
+// CreateResponse returns the result of a CreateRequest
+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)
+}
+
+// LayerType returns LayerTypeCreateResponse
+func (omci *CreateResponse) LayerType() gopacket.LayerType {
+	return LayerTypeCreateResponse
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *CreateResponse) CanDecode() gopacket.LayerClass {
+	return LayerTypeCreateResponse
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *CreateResponse) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize, offset int
+	if omci.Extended {
+		offset = 6
+		hdrSize = offset + 1 // Plus 2 more if result = 3
+	} else {
+		offset = 4
+		hdrSize = offset + 3
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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[offset])
+	if omci.Result == me.ParameterError {
+		// Optional attribute execution mask (2 octets) is required
+		if len(data) < hdrSize+2 {
+			p.SetTruncated()
+			return errors.New("frame too small")
+		}
+		omci.AttributeExecutionMask = binary.BigEndian.Uint16(data[offset+1:])
+	}
+	return nil
+}
+
+func decodeCreateResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &CreateResponse{}
+	omci.MsgLayerType = LayerTypeCreateResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+func decodeCreateResponseExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &CreateResponse{}
+	omci.MsgLayerType = LayerTypeCreateResponse
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Create Response message
+func (omci *CreateResponse) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	var offset, extra int
+	if omci.Extended {
+		offset = 2
+	}
+	if omci.Result == me.ParameterError {
+		extra = 2
+	}
+	bytes, err := b.AppendBytes(offset + 1 + extra)
+	if err != nil {
+		return err
+	}
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, uint16(1+extra))
+	}
+	bytes[offset] = byte(omci.Result)
+	if omci.Result == me.ParameterError {
+		binary.BigEndian.PutUint16(bytes[offset+1:], omci.AttributeExecutionMask)
+	}
+	return nil
+}
diff --git a/create_test.go b/create_test.go
new file mode 100644
index 0000000..0207800
--- /dev/null
+++ b/create_test.go
@@ -0,0 +1,750 @@
+/*
+ * 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_test
+
+import (
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/opencord/omci-lib-go/meframe"
+	"github.com/stretchr/testify/assert"
+	"strings"
+	"testing"
+)
+
+func TestCreateRequestDecode(t *testing.T) {
+	goodMessage := "000C440A010C01000400800003010000" +
+		"00000000000000000000000000000000" +
+		"000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeCreateRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0xc), omciMsg.TransactionID)
+	assert.Equal(t, CreateRequestType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeCreateRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*CreateRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeCreateRequest, request.LayerType())
+	assert.Equal(t, LayerTypeCreateRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, me.GemPortNetworkCtpClassID, request.EntityClass)
+	assert.Equal(t, uint16(0x100), request.EntityInstance)
+
+	attributes := request.Attributes
+	assert.NotNil(t, attributes)
+
+	// As this is a create request, gather up all set-by-create attributes
+	// make sure we got them all, and nothing else
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(request.EntityClass)
+	assert.NotNil(t, omciErr)
+	assert.Equal(t, omciErr.StatusCode(), me.Success)
+
+	attrDefs := meDefinition.GetAttributeDefinitions()
+
+	sbcMask := getSbcMask(meDefinition)
+	for index := uint(1); index < uint(len(attrDefs)); index++ {
+		attrName := attrDefs[index].GetName()
+
+		if sbcMask&uint16(1<<(uint)(16-index)) != 0 {
+			_, ok3 := attributes[attrName]
+			assert.True(t, ok3)
+		} else {
+			_, ok3 := attributes[attrName]
+			assert.False(t, ok3)
+		}
+		//fmt.Printf("Name: %v, Value: %v\n", attrName, attributes[attrName])
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err = gopacket.SerializeLayers(buffer, options, omciMsg, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestCreateRequestSerialize(t *testing.T) {
+	goodMessage := "000C440A010C0100040080000301000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x0c,
+		MessageType:   CreateRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &CreateRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.GemPortNetworkCtpClassID,
+			EntityInstance: uint16(0x100),
+		},
+		Attributes: me.AttributeValueMap{
+			"PortId":                              0x400,
+			"TContPointer":                        0x8000,
+			"Direction":                           3,
+			"TrafficManagementPointerForUpstream": 0x100,
+			"TrafficDescriptorProfilePointerForUpstream":   0,
+			"PriorityQueuePointerForDownStream":            0,
+			"TrafficDescriptorProfilePointerForDownstream": 0,
+			"EncryptionKeyRing":                            0,
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestCreateRequestZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0000,
+		MessageType:   CreateRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &CreateRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.GemPortNetworkCtpClassID,
+			EntityInstance: uint16(0x100),
+		},
+		Attributes: me.AttributeValueMap{
+			"PortId":                              0x400,
+			"TContPointer":                        0x8000,
+			"Direction":                           3,
+			"TrafficManagementPointerForUpstream": 0x100,
+			"TrafficDescriptorProfilePointerForUpstream":   0,
+			"PriorityQueuePointerForDownStream":            0,
+			"TrafficDescriptorProfilePointerForDownstream": 0,
+			"EncryptionKeyRing":                            0,
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestCreateResponseDecode(t *testing.T) {
+	goodMessage := "0157240a01100001000000000000000000000000000000000000000000000000000000000000000000000028a9ccbeb9"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeCreateResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0157), omciMsg.TransactionID)
+	assert.Equal(t, CreateResponseType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeCreateResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*CreateResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeCreateResponse, response.LayerType())
+	assert.Equal(t, LayerTypeCreateResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestCreateResponseSerialize(t *testing.T) {
+	goodMessage := "0157240a01100001000000000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x0157,
+		MessageType:   CreateResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &CreateResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.GalEthernetProfileClassID,
+			EntityInstance: uint16(1),
+		},
+		Result:                 me.Success,
+		AttributeExecutionMask: uint16(0),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestCreateResponseZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   CreateResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &CreateResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.GalEthernetProfileClassID,
+			EntityInstance: uint16(1),
+		},
+		Result:                 me.Success,
+		AttributeExecutionMask: uint16(0),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestExtendedCreateRequestDecode(t *testing.T) {
+	goodMessage := "000C440B010C0100000E0400800003010000000000000000"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+	// TODO: Trailing optional SBC attributes can be omitted at the option
+	//       of the transmitter
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeCreateRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0xc), omciMsg.TransactionID)
+	assert.Equal(t, CreateRequestType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(14), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeCreateRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*CreateRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeCreateRequest, request.LayerType())
+	assert.Equal(t, LayerTypeCreateRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, me.GemPortNetworkCtpClassID, request.EntityClass)
+	assert.Equal(t, uint16(0x100), request.EntityInstance)
+
+	attributes := request.Attributes
+	assert.NotNil(t, attributes)
+
+	// As this is a create request, gather up all set-by-create attributes
+	// make sure we got them all, and nothing else
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(request.EntityClass)
+	assert.NotNil(t, omciErr)
+	assert.Equal(t, omciErr.StatusCode(), me.Success)
+
+	attrDefs := meDefinition.GetAttributeDefinitions()
+
+	sbcMask := getSbcMask(meDefinition)
+	for index := uint(1); index < uint(len(attrDefs)); index++ {
+		attrName := attrDefs[index].GetName()
+
+		if sbcMask&uint16(1<<(uint)(16-index)) != 0 {
+			_, ok3 := attributes[attrName]
+			assert.True(t, ok3)
+		} else {
+			_, ok3 := attributes[attrName]
+			assert.False(t, ok3)
+		}
+		//fmt.Printf("Name: %v, Value: %v\n", attrName, attributes[attrName])
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err = gopacket.SerializeLayers(buffer, options, omciMsg, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedCreateRequestSerialize(t *testing.T) {
+	goodMessage := "000C440B010C0100000E0400800003010000000000000000"
+	omciLayer := &OMCI{
+		TransactionID:    0x0c,
+		MessageType:      CreateRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &CreateRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.GemPortNetworkCtpClassID,
+			EntityInstance: uint16(0x100),
+			Extended:       true,
+		},
+		Attributes: me.AttributeValueMap{
+			"PortId":                              0x0400,
+			"TContPointer":                        0x8000,
+			"Direction":                           3,
+			"TrafficManagementPointerForUpstream": 0x100,
+			"TrafficDescriptorProfilePointerForUpstream":   0,
+			"PriorityQueuePointerForDownStream":            0,
+			"TrafficDescriptorProfilePointerForDownstream": 0,
+			"EncryptionKeyRing":                            0,
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestExtendedCreateResponseDecode(t *testing.T) {
+	goodMessage := "0157240b01100001000100"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+	// TODO: Also test sending reason code 3
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeCreateResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0157), omciMsg.TransactionID)
+	assert.Equal(t, CreateResponseType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(1), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeCreateResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*CreateResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeCreateResponse, response.LayerType())
+	assert.Equal(t, LayerTypeCreateResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, me.Success, response.Result)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedCreateResponseSerialize(t *testing.T) {
+	goodMessage := "0157240b01100001000100"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0157,
+		MessageType:      CreateResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &CreateResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.GalEthernetProfileClassID,
+			EntityInstance: uint16(1),
+			Extended:       true,
+		},
+		Result:                 me.Success,
+		AttributeExecutionMask: uint16(0), // Optional since success
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestCreate8021pMapperService_profile(t *testing.T) {
+	create8021pMapperServiceProfile := "0007440A00828000ffffffffffffffff" +
+		"ffffffffffffffffffff000000000000" +
+		"000000000000000000000028"
+
+	data, err := stringToPacket(create8021pMapperServiceProfile)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, packet)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, uint16(7), omciMsg.TransactionID)
+	assert.Equal(t, CreateRequestType, omciMsg.MessageType)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeCreateRequest)
+	assert.NotNil(t, msgLayer)
+
+	createRequest, ok2 := msgLayer.(*CreateRequest)
+	assert.True(t, ok2)
+	assert.Equal(t, me.Ieee8021PMapperServiceProfileClassID, createRequest.EntityClass)
+	assert.Equal(t, uint16(0x8000), createRequest.EntityInstance)
+
+	attributes := createRequest.Attributes
+	assert.NotNil(t, attributes)
+	assert.Equal(t, 13, len(attributes))
+
+	// As this is a create request, gather up all set-by-create attributes
+	// make sure we got them all, and nothing else
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(createRequest.EntityClass)
+	assert.NotNil(t, omciErr)
+	assert.Equal(t, me.Success, omciErr.StatusCode())
+
+	attrDefs := meDefinition.GetAttributeDefinitions()
+
+	for index := uint(1); index <= uint(9); index++ {
+		attrName := attrDefs[index].GetName()
+		value, ok := attributes[attrName]
+		assert.True(t, ok)
+
+		value16, ok3 := value.(uint16)
+		assert.True(t, ok3)
+		assert.Equal(t, uint16(0xffff), value16)
+	}
+
+	sbcMask := getSbcMask(meDefinition)
+	for index := uint(1); index < uint(len(attrDefs)); index++ {
+		attrName := attrDefs[index].GetName()
+
+		if sbcMask&uint16(1<<(uint)(16-index)) != 0 {
+			_, ok3 := attributes[attrName]
+			assert.True(t, ok3)
+		} else {
+			_, ok3 := attributes[attrName]
+			assert.False(t, ok3)
+		}
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err = gopacket.SerializeLayers(buffer, options, omciMsg, createRequest)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(create8021pMapperServiceProfile), reconstituted)
+}
+
+func TestCreateGalEthernetProfile(t *testing.T) {
+	createGalEthernetProfile := "0002440A011000010030000000000000" +
+		"00000000000000000000000000000000" +
+		"000000000000000000000028"
+
+	data, err := stringToPacket(createGalEthernetProfile)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, packet)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, uint16(2), omciMsg.TransactionID)
+	assert.Equal(t, CreateRequestType, omciMsg.MessageType)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeCreateRequest)
+	assert.NotNil(t, msgLayer)
+
+	omciMsg2, ok2 := msgLayer.(*CreateRequest)
+	assert.True(t, ok2)
+	assert.Equal(t, me.GalEthernetProfileClassID, omciMsg2.EntityClass)
+	assert.Equal(t, uint16(1), omciMsg2.EntityInstance)
+
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err = gopacket.SerializeLayers(buffer, options, omciMsg, omciMsg2)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(createGalEthernetProfile), reconstituted)
+}
+
+func TestCreate_macBridgeService_profile(t *testing.T) {
+	var createMacBridgeServiceProfile = "000B440A002D02010001008000140002" +
+		"000f0001000000000000000000000000" +
+		"000000000000000000000028"
+
+	data, err := stringToPacket(createMacBridgeServiceProfile)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, packet)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, uint16(0xb), omciMsg.TransactionID)
+	assert.Equal(t, CreateRequestType, omciMsg.MessageType)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeCreateRequest)
+	assert.NotNil(t, msgLayer)
+
+	createRequest, ok2 := msgLayer.(*CreateRequest)
+	assert.True(t, ok2)
+	assert.Equal(t, me.MacBridgeServiceProfileClassID, createRequest.EntityClass)
+	assert.Equal(t, uint16(0x201), createRequest.EntityInstance)
+
+	attributes := createRequest.Attributes
+	assert.NotNil(t, attributes)
+
+	// As this is a create request, gather up all set-by-create attributes
+	// make sure we got them all, and nothing else
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(createRequest.EntityClass)
+	assert.NotNil(t, omciErr)
+	assert.Equal(t, me.Success, omciErr.StatusCode())
+
+	attrDefs := meDefinition.GetAttributeDefinitions()
+
+	sbcMask := getSbcMask(meDefinition)
+	for index := uint(1); index < uint(len(attrDefs)); index++ {
+		attrName := attrDefs[index].GetName()
+
+		if sbcMask&uint16(1<<(uint)(16-index)) != 0 {
+			_, ok3 := attributes[attrName]
+			assert.True(t, ok3)
+		} else {
+			_, ok3 := attributes[attrName]
+			assert.False(t, ok3)
+		}
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err = gopacket.SerializeLayers(buffer, options, omciMsg, createRequest)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(createMacBridgeServiceProfile), reconstituted)
+}
+
+func TestCreateGemPortNetworkCtp(t *testing.T) {
+	createGemPortNetworkCtp := "000C440A010C01000400800003010000" +
+		"00000000000000000000000000000000" +
+		"000000000000000000000028"
+
+	data, err := stringToPacket(createGemPortNetworkCtp)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, packet)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, uint16(0xc), omciMsg.TransactionID)
+	assert.Equal(t, CreateRequestType, omciMsg.MessageType)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeCreateRequest)
+	assert.NotNil(t, msgLayer)
+
+	createRequest, ok2 := msgLayer.(*CreateRequest)
+	assert.True(t, ok2)
+	assert.Equal(t, me.GemPortNetworkCtpClassID, createRequest.EntityClass)
+	assert.Equal(t, uint16(0x100), createRequest.EntityInstance)
+
+	attributes := createRequest.Attributes
+	assert.NotNil(t, attributes)
+
+	// As this is a create request, gather up all set-by-create attributes
+	// make sure we got them all, and nothing else
+	meDefinition, omciErr := me.LoadManagedEntityDefinition(createRequest.EntityClass)
+	assert.NotNil(t, omciErr)
+	assert.Equal(t, me.Success, omciErr.StatusCode())
+
+	attrDefs := meDefinition.GetAttributeDefinitions()
+
+	sbcMask := getSbcMask(meDefinition)
+	for index := uint(1); index < uint(len(attrDefs)); index++ {
+		attrName := attrDefs[index].GetName()
+
+		if sbcMask&uint16(1<<(uint)(16-index)) != 0 {
+			_, ok3 := attributes[attrName]
+			assert.True(t, ok3)
+		} else {
+			_, ok3 := attributes[attrName]
+			assert.False(t, ok3)
+		}
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err = gopacket.SerializeLayers(buffer, options, omciMsg, createRequest)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(createGemPortNetworkCtp), reconstituted)
+}
+
+// TestCreateMulticastOperationsProfileMe tests a hand-coded managed entity in the generated
+// subdirectory
+func TestCreateMulticastOperationsProfileMe(t *testing.T) {
+	// Test various create request for this ME
+	meParams := me.ParamData{
+		EntityID: uint16(0x501),
+		Attributes: me.AttributeValueMap{
+			"IgmpVersion":                      2,
+			"IgmpFunction":                     0,
+			"ImmediateLeave":                   0,
+			"UpstreamIgmpTci":                  0,
+			"Robustness":                       2,
+			"QuerierIpAddress":                 0,
+			"QueryInterval":                    125,
+			"QueryMaxResponseTime":             100,
+			"LastMemberQueryInterval":          10,
+			"UnauthorizedJoinRequestBehaviour": 0,
+			"UpstreamIgmpRate":                 0,
+			"UpstreamIgmpTagControl":           0,
+			"DownstreamIgmpAndMulticastTci":    []byte{0, 0, 0},
+		},
+	}
+	meInstance, newErr := me.NewMulticastOperationsProfile(meParams)
+	assert.NotNil(t, meInstance)
+	assert.Equal(t, newErr.StatusCode(), me.Success)
+
+	tid := uint16(123)
+	frame, omciErr := meframe.GenFrame(meInstance, CreateRequestType, meframe.TransactionID(tid))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, omciObj.MessageType, CreateRequestType)
+	assert.Equal(t, omciObj.DeviceIdentifier, BaselineIdent)
+
+	msgLayer := packet.Layer(LayerTypeCreateRequest)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*CreateRequest)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, msgObj.EntityClass, meInstance.GetClassID())
+	assert.Equal(t, msgObj.EntityInstance, meInstance.GetEntityID())
+}
diff --git a/delete.go b/delete.go
new file mode 100644
index 0000000..6502b8a
--- /dev/null
+++ b/delete.go
@@ -0,0 +1,210 @@
+/*
+ * 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"
+	"fmt"
+	"github.com/google/gopacket"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+type DeleteRequest struct {
+	MeBasePacket
+}
+
+func (omci *DeleteRequest) String() string {
+	return fmt.Sprintf("%v", omci.MeBasePacket.String())
+}
+
+// LayerType returns LayerTypeDeleteRequest
+func (omci *DeleteRequest) LayerType() gopacket.LayerType {
+	return LayerTypeDeleteRequest
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *DeleteRequest) CanDecode() gopacket.LayerClass {
+	return LayerTypeDeleteRequest
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *DeleteRequest) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6
+	} else {
+		hdrSize = 4
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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)
+}
+
+func decodeDeleteRequestExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &DeleteRequest{}
+	omci.MsgLayerType = LayerTypeDeleteRequest
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Delete Request message
+func (omci *DeleteRequest) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	if omci.Extended {
+		bytes, err := b.AppendBytes(2)
+		if err != nil {
+			return err
+		}
+		binary.BigEndian.PutUint16(bytes, 0)
+	}
+	return nil
+}
+
+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)
+}
+
+// LayerType returns LayerTypeDeleteResponse
+func (omci *DeleteResponse) LayerType() gopacket.LayerType {
+	return LayerTypeDeleteResponse
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *DeleteResponse) CanDecode() gopacket.LayerClass {
+	return LayerTypeDeleteResponse
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *DeleteResponse) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6 + 1
+	} else {
+		hdrSize = 4 + 1
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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")
+	}
+	offset := hdrSize - 1
+	omci.Result = me.Results(data[offset])
+	return nil
+}
+
+func decodeDeleteResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &DeleteResponse{}
+	omci.MsgLayerType = LayerTypeDeleteResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+func decodeDeleteResponseExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &DeleteResponse{}
+	omci.MsgLayerType = LayerTypeDeleteResponse
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Delete Response message
+func (omci *DeleteResponse) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	} else {
+		offset = 0
+	}
+	bytes, err := b.AppendBytes(offset + 1)
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, 1)
+	}
+	if err != nil {
+		return err
+	}
+	bytes[offset] = byte(omci.Result)
+	return nil
+}
diff --git a/delete_test.go b/delete_test.go
new file mode 100644
index 0000000..d6efc27
--- /dev/null
+++ b/delete_test.go
@@ -0,0 +1,339 @@
+/*
+ * 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_test
+
+import (
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/stretchr/testify/assert"
+	"strings"
+	"testing"
+)
+
+func TestDeleteRequestDecode(t *testing.T) {
+	goodMessage := "0211460a00ab0202000000000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeDeleteRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0211), omciMsg.TransactionID)
+	assert.Equal(t, DeleteRequestType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeDeleteRequest)
+
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*DeleteRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeDeleteRequest, request.LayerType())
+	assert.Equal(t, LayerTypeDeleteRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestDeleteRequestSerialize(t *testing.T) {
+	goodMessage := "0211460a00ab0202000000000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x0211,
+		MessageType:   DeleteRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &DeleteRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x202),
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestDeleteRequestZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0000,
+		MessageType:   DeleteRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &DeleteRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x202),
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestDeleteResponseDecode(t *testing.T) {
+	goodMessage := "0211260a00ab0202000000000000000000000000000000000000000000000000000000000000000000000028013437fb"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeDeleteResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0211), omciMsg.TransactionID)
+	assert.Equal(t, DeleteResponseType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeDeleteResponse)
+
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*DeleteResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeDeleteResponse, response.LayerType())
+	assert.Equal(t, LayerTypeDeleteResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestDeleteResponseSerialize(t *testing.T) {
+	goodMessage := "0211260a00ab0202000000000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x0211,
+		MessageType:   DeleteResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &DeleteResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x202),
+		},
+		Result: me.Success,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestDeleteResponseZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   DeleteResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &DeleteResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x202),
+		},
+		Result: me.Success,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestExtendedDeleteRequestDecode(t *testing.T) {
+	goodMessage := "0211460b00ab02020000"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeDeleteRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0211), omciMsg.TransactionID)
+	assert.Equal(t, DeleteRequestType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(0), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeDeleteRequest)
+
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*DeleteRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeDeleteRequest, request.LayerType())
+	assert.Equal(t, LayerTypeDeleteRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedDeleteRequestSerialize(t *testing.T) {
+	goodMessage := "0211460b00ab02020000"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0211,
+		MessageType:      DeleteRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &DeleteRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x202),
+			Extended:       true,
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestExtendedDeleteResponseDecode(t *testing.T) {
+	goodMessage := "0211260b00ab0202000103"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeDeleteResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0211), omciMsg.TransactionID)
+	assert.Equal(t, DeleteResponseType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(1), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeDeleteResponse)
+
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*DeleteResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeDeleteResponse, response.LayerType())
+	assert.Equal(t, LayerTypeDeleteResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, me.ParameterError, response.Result)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedDeleteResponseSerialize(t *testing.T) {
+	goodMessage := "0211260b00ab0202000103"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0211,
+		MessageType:      DeleteResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &DeleteResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x202),
+			Extended:       true,
+		},
+		Result: me.ParameterError,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
diff --git a/generated/aal5performancemonitoringhistorydata.go b/generated/aal5performancemonitoringhistorydata.go
index 560466d..50dd54a 100644
--- a/generated/aal5performancemonitoringhistorydata.go
+++ b/generated/aal5performancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // Aal5PerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity AAL5 performance monitoring history data
-const Aal5PerformanceMonitoringHistoryDataClassID ClassID = ClassID(18)
+const Aal5PerformanceMonitoringHistoryDataClassID = ClassID(18) // 0x0012
 
 var aal5performancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// Aal5PerformanceMonitoringHistoryData (class ID #18)
+// Aal5PerformanceMonitoringHistoryData (Class ID: #18 / 0x0012)
 //	This ME collects PM data as a result of performing segmentation and reassembly (SAR) and
 //	convergence sublayer (CS) level protocol monitoring. Instances of this ME are created and
 //	deleted by the OLT.
@@ -44,13 +44,11 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the IW VCC TP. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the IW VCC TP. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -58,26 +56,25 @@
 //			data 2 ME is optional. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Sum Of Invalid Cs Field Errors
-//			Sum of invalid CS field errors: This attribute counts the sum of invalid CS field errors. For
-//			AAL type 5, this attribute is a single count of the number of CS PDUs discarded due to one of
-//			the following error conditions: invalid common part indicator (CPI), oversized received SDU, or
-//			length violation. (R) (mandatory) (4-bytes)
-//
-//		Crc Violations
-//			CRC violations: This attribute counts CRC violations detected on incoming SAR PDUs. (R)
+//			This attribute counts the sum of invalid CS field errors. For AAL type 5, this attribute is a
+//			single count of the number of CS PDUs discarded due to one of the following error conditions:
+//			invalid common part indicator (CPI), oversized received SDU, or length violation. (R)
 //			(mandatory) (4-bytes)
 //
+//		Crc Violations
+//			This attribute counts CRC violations detected on incoming SAR PDUs. (R) (mandatory) (4-bytes)
+//
 //		Reassembly Timer Expirations
-//			Reassembly timer expirations: This attribute counts reassembly timer expirations. (R) (mandatory
-//			if reassembly timer is implemented) (4-bytes)
+//			This attribute counts reassembly timer expirations. (R) (mandatory if reassembly timer is
+//			implemented) (4-bytes)
 //
 //		Buffer Overflows
-//			Buffer overflows: This attribute counts the number of times where there was not enough buffer
-//			space for a reassembled packet. (R) (mandatory) (4-bytes)
+//			This attribute counts the number of times where there was not enough buffer space for a
+//			reassembled packet. (R) (mandatory) (4-bytes)
 //
 //		Encap Protocol Errors
-//			Encap protocol errors: This attribute counts the number of times that [IETF RFC 2684]
-//			encapsulation protocol detected a bad header. (R) (mandatory) (4-bytes)
+//			This attribute counts the number of times that [IETF RFC 2684] encapsulation protocol detected a
+//			bad header. (R) (mandatory) (4-bytes)
 //
 type Aal5PerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/aal5profile.go b/generated/aal5profile.go
index 9de7866..bbade42 100644
--- a/generated/aal5profile.go
+++ b/generated/aal5profile.go
@@ -27,11 +27,11 @@
 
 // Aal5ProfileClassID is the 16-bit ID for the OMCI
 // Managed entity AAL5 profile
-const Aal5ProfileClassID ClassID = ClassID(16)
+const Aal5ProfileClassID = ClassID(16) // 0x0010
 
 var aal5profileBME *ManagedEntityDefinition
 
-// Aal5Profile (class ID #16)
+// Aal5Profile (Class ID: #16 / 0x0010)
 //	This ME organizes data that describe the AAL type 5 processing functions of the ONU. It is used
 //	with the IW VCC TP ME.
 //
@@ -42,17 +42,37 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Max Cpcs Pdu Size
-//			Max CPCS PDU size: This attribute specifies the maximum CPCS PDU size to be transmitted over the
-//			connection in both upstream and downstream directions. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute specifies the maximum CPCS PDU size to be transmitted over the connection in both
+//			upstream and downstream directions. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Aal Mode
+//			This attribute specifies the AAL mode as follows.
+//
+//			0	Message assured
+//
+//			1	Message unassured
+//
+//			2	Streaming assured
+//
+//			3	Streaming non assured
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Sscs Type
+//			This attribute specifies the SSCS type for the AAL. Valid values are as follows.
+//
+//			0	Null
+//
+//			1	Data SSCS based on SSCOP, assured operation
+//
+//			2	Data SSCS based on SSCOP, non-assured operation
+//
+//			3	Frame relay SSCS
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
 type Aal5Profile struct {
diff --git a/generated/ani-g.go b/generated/ani-g.go
index 022fcbf..0e13c5c 100644
--- a/generated/ani-g.go
+++ b/generated/ani-g.go
@@ -27,11 +27,11 @@
 
 // AniGClassID is the 16-bit ID for the OMCI
 // Managed entity ANI-G
-const AniGClassID ClassID = ClassID(263)
+const AniGClassID = ClassID(263) // 0x0107
 
 var anigBME *ManagedEntityDefinition
 
-// AniG (class ID #263)
+// AniG (Class ID: #263 / 0x0107)
 //	This ME organizes data associated with each access network interface supported by a GPON ONU.
 //	The ONU automatically creates one instance of this ME for each PON physical port.
 //
@@ -40,29 +40,52 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Its value
-//			indicates the physical position of the PON interface. The first byte is the slot ID, defined in
-//			clause 9.1.5. The second byte is the port ID. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Its value indicates the physical
+//			position of the PON interface. The first byte is the slot ID, defined in clause 9.1.5. The
+//			second byte is the port ID. (R) (mandatory) (2-bytes)
 //
 //		Sr Indication
-//			SR indication: This Boolean attribute indicates the ONU's capability to report queue status for
-//			DBA. The value true means that status reporting is available for all TCONTs that are associated
-//			with the ANI. (R) (mandatory) (1-byte)
+//			This Boolean attribute indicates the ONU's capability to report queue status for DBA. The value
+//			true means that status reporting is available for all TCONTs that are associated with the ANI.
+//			(R) (mandatory) (1-byte)
 //
 //		Total TCont Number
-//			Total TCONT number: This attribute indicates the total number of T-CONTs that can be supported
-//			on this ANI. (R) (mandatory) (2-bytes)
+//			This attribute indicates the total number of T-CONTs that can be supported on this ANI. (R)
+//			(mandatory) (2-bytes)
 //
 //		Gem Block Length
+//			This attribute specifies the queue occupancy reporting granularity for DBA, expressed in bytes.
+//			This attribute is meaningful only in ITUT G.984.x systems. (R, W) (mandatory) (2 bytes)
+//
+//			In ITU-T G.984 systems, the value set by the OLT is used by all TCONTs on this ANI. Upon ME
+//			instantiation, the ONU sets this attribute to 48. See [ITUT G.984.3] for further details.
+//
 //			In all other ITU-T PON systems, the unit for queue occupancy reporting is fixed in at 4-bytes by
 //			the respective TC layer specification.
 //
 //		Piggyback Dba Reporting
+//			This attribute indicates the ONU's piggyback DBA reporting format capabilities. [ITUT G.984.3]
+//			defines two possible piggyback reporting modes. For reporting mode 0, the single field is the
+//			entire report. For reporting mode 1, the DBA report is two fields long. Mode 0 is mandatory for
+//			ITU-T G.984 ONUs that support piggyback DBA reporting; mode 1 is optional. Subsequent PON
+//			specifications allows only one mode, which should be reported in this attribute as code point 0.
+//
+//			The following coding indicates the ONU's piggyback DBA reporting mode capabilities:
+//
+//			0	Mode 0 only
+//
+//			1	Modes 0 and 1
+//
+//			2	Deprecated
+//
+//			3	Deprecated
+//
+//			4	Piggyback DBA reporting not supported
+//
 //			(R) (mandatory) (1-byte)
 //
 //		Deprecated
-//			Deprecated:	This attribute should be set to 0 by the ONU and ignored by the OLT. (R) (mandatory)
-//			(1-byte)
+//			This attribute should be set to 0 by the ONU and ignored by the OLT. (R) (mandatory) (1-byte)
 //
 //		Signal Fail Threshold
 //			Signal fail (SF) threshold: This attribute specifies the downstream bit error rate (BER)
@@ -76,47 +99,56 @@
 //			ONU sets this attribute to 9. (R,-W) (mandatory) (1-byte)
 //
 //		Arc
-//			ARC:	See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Arc Interval
-//			ARC interval: See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Optical Signal Level
-//			Optical signal level: This attribute reports the current measurement of the total downstream
-//			optical signal level. Its value is a 2s complement integer referred to 1- mW (i.e., 1-dBm), with
-//			0.002 dB granularity. (R) (optional) (2-bytes)
+//			This attribute reports the current measurement of the total downstream optical signal level. Its
+//			value is a 2s complement integer referred to 1- mW (i.e., 1-dBm), with 0.002 dB granularity. (R)
+//			(optional) (2-bytes)
 //
 //		Lower Optical Threshold
-//			Lower optical threshold: This attribute specifies the optical level the ONU uses to declare the
-//			downstream low received optical power alarm. Valid values are  -127 dBm (coded as 254) to 0 dBm
-//			(coded as 0) in 0.5 dB increments. The default value 0xFF selects the ONU's internal policy.
-//			(R,-W) (optional) (1-byte)
+//			This attribute specifies the optical level the ONU uses to declare the downstream low received
+//			optical power alarm. Valid values are  -127 dBm (coded as 254) to 0 dBm (coded as 0) in 0.5 dB
+//			increments. The default value 0xFF selects the ONU's internal policy. (R,-W) (optional) (1-byte)
 //
 //		Upper Optical Threshold
-//			Upper optical threshold: This attribute specifies the optical level the ONU uses to declare the
-//			downstream high received optical power alarm. Valid values are  -127 dBm (coded as 254) to 0 dBm
-//			(coded as 0) in 0.5 dB increments. The default value 0xFF selects the ONU's internal policy.
-//			(R,-W) (optional) (1-byte)
+//			This attribute specifies the optical level the ONU uses to declare the downstream high received
+//			optical power alarm. Valid values are  -127 dBm (coded as 254) to 0 dBm (coded as 0) in 0.5 dB
+//			increments. The default value 0xFF selects the ONU's internal policy. (R,-W) (optional) (1-byte)
 //
 //		Onu Response Time
+//			This attribute indicates the ONU's actual response time. This attribute is in the range
+//			34..36-us. Although this attribute is expressed in nanoseconds, its accuracy is likely to be
+//			more coarse. Furthermore, the value may change from one activation cycle to the next. Valid
+//			values are:
+//
+//			0 (Null, function not supported)
+//
+//			34000 to 36000 (response time in nanoseconds)
+//
+//			All other values reserved
+//
 //			(R) (optional) (2-bytes)
 //
 //		Transmit Optical Level
-//			Transmit optical level: This attribute reports the current measurement of mean optical launch
-//			power. Its value is a 2s complement integer referred to 1-mW (i.e., 1-dBm), with 0.002 dB
-//			granularity. (R) (optional) (2-bytes)
+//			This attribute reports the current measurement of mean optical launch power. Its value is a 2s
+//			complement integer referred to 1-mW (i.e., 1-dBm), with 0.002 dB granularity. (R) (optional)
+//			(2-bytes)
 //
 //		Lower Transmit Power Threshold
-//			Lower transmit power threshold: This attribute specifies the minimum mean optical launch power
-//			that the ONU uses to declare the low transmit optical power alarm. Its value is a 2s complement
-//			integer referred to 1-mW (i.e., dBm), with 0.5-dB granularity. The default value -63.5 (0x81)
-//			selects the ONU's internal policy. (R,-W) (optional) (1-byte)
+//			This attribute specifies the minimum mean optical launch power that the ONU uses to declare the
+//			low transmit optical power alarm. Its value is a 2s complement integer referred to 1-mW (i.e.,
+//			dBm), with 0.5-dB granularity. The default value -63.5 (0x81) selects the ONU's internal policy.
+//			(R,-W) (optional) (1-byte)
 //
 //		Upper Transmit Power Threshold
-//			Upper transmit power threshold: This attribute specifies the maximum mean optical launch power
-//			that the ONU uses to declare the high transmit optical power alarm. Its value is a 2s complement
-//			integer referred to 1-mW (i.e., dBm), with 0.5-dB granularity. The default value -63.5 (0x81)
-//			selects the ONU's internal policy. (R,-W) (optional) (1-byte)
+//			This attribute specifies the maximum mean optical launch power that the ONU uses to declare the
+//			high transmit optical power alarm. Its value is a 2s complement integer referred to 1-mW (i.e.,
+//			dBm), with 0.5-dB granularity. The default value -63.5 (0x81) selects the ONU's internal policy.
+//			(R,-W) (optional) (1-byte)
 //
 type AniG struct {
 	ManagedEntityDefinition
@@ -147,7 +179,7 @@
 			10: Uint16Field("OpticalSignalLevel", SignedIntegerAttributeType, 0x0040, 0, mapset.NewSetWith(Read), false, true, false, 10),
 			11: ByteField("LowerOpticalThreshold", SignedIntegerAttributeType, 0x0020, 255, mapset.NewSetWith(Read, Write), false, true, false, 11),
 			12: ByteField("UpperOpticalThreshold", SignedIntegerAttributeType, 0x0010, 255, mapset.NewSetWith(Read, Write), false, true, false, 12),
-			13: Uint16Field("OnuResponseTime", UnsignedIntegerAttributeType, 0x0008, 0, mapset.NewSetWith(Read), false, true, false, 13),
+			13: Uint16Field("OnuResponseTime", UnsignedIntegerAttributeType, 0x0008, 35000, mapset.NewSetWith(Read), false, true, false, 13),
 			14: Uint16Field("TransmitOpticalLevel", SignedIntegerAttributeType, 0x0004, 0, mapset.NewSetWith(Read), false, true, false, 14),
 			15: ByteField("LowerTransmitPowerThreshold", SignedIntegerAttributeType, 0x0002, 129, mapset.NewSetWith(Read, Write), false, true, false, 15),
 			16: ByteField("UpperTransmitPowerThreshold", SignedIntegerAttributeType, 0x0001, 129, mapset.NewSetWith(Read, Write), false, true, false, 16),
diff --git a/generated/attribute.go b/generated/attribute.go
index 58bd6cf..de20130 100644
--- a/generated/attribute.go
+++ b/generated/attribute.go
@@ -52,7 +52,7 @@
 	CounterAttributeType                              // Incrementing counter
 )
 
-// AttributeDefinitionMap is a map of attribute definitions with the attribute index (0..15)
+// AttributeDefinitionMap is a map of attribute definitions with the attribute index (0..16)
 // as the key
 type AttributeDefinitionMap map[uint]AttributeDefinition
 
@@ -72,6 +72,12 @@
 	Deprecated    bool // If true, attribute is deprecated
 }
 
+// TableRows is used by the SetTable request/response
+type TableRows struct {
+	NumRows int    // Number of rows of 'AttributeDefinition.Size' length
+	Rows    []byte // 0..NumRows rows of attribute data of size 'AttributeDefinition.Size'
+}
+
 func (attr *AttributeDefinition) String() string {
 	return fmt.Sprintf("AttributeDefinition: %v (%v/%v): Size: %v, Default: %v, Access: %v",
 		attr.GetName(), attr.AttributeType, attr.GetIndex(), attr.GetSize(), attr.GetDefault(), attr.GetAccess())
@@ -80,7 +86,7 @@
 // GetName returns the attribute's name
 func (attr AttributeDefinition) GetName() string { return attr.Name }
 
-// GetIndex returns the attribute index )0..15)
+// GetIndex returns the attribute index )0..16)
 func (attr AttributeDefinition) GetIndex() uint { return attr.Index }
 
 // GetDefault provides the default value for an attribute if not specified
@@ -392,14 +398,32 @@
 		if size != 0 && len(data) < attr.GetSize() {
 			df.SetTruncated()
 			return nil, NewMessageTruncatedError("packet too small for field")
-		} else if size == 0 {
+		}
+		if size == 0 {
 			return nil, NewProcessingError("table attributes with no size are not supported: %v", attr.Name)
 		}
 		return data, nil
 
 	case byte(SetTable) | AR: // Set Table Request
-		// TODO: Only baseline supported at this time
-		return nil, errors.New("attribute encode for set-table-request not yet supported")
+		// SetTableRequestType will be composed of zero or more row of a fixed size (based on ME)
+		// and will be saved to a TableRow struct for the consumer's use
+		size := attr.GetSize()
+		if size == 0 {
+			return nil, NewProcessingError("table attributes with no size are not supported: %v", attr.Name)
+		}
+		if len(data)%size != 0 {
+			df.SetTruncated()
+			return nil, NewMessageTruncatedError("packet does not contain an integral number of rows")
+		}
+		if len(data) == 0 {
+			return TableRows{}, nil
+		}
+		rows := TableRows{
+			NumRows: len(data) / size,
+			Rows:    make([]byte, len(data)),
+		}
+		copy(rows.Rows, data)
+		return rows, nil
 	}
 }
 
@@ -449,8 +473,22 @@
 		break
 
 	case byte(SetTable) | AR: // Set Table Request
-		// TODO: Only baseline supported at this time
-		return 0, errors.New("attribute encode for set-table-request not yet supported")
+		if rows, ok := value.(TableRows); ok {
+			size := attr.GetSize()
+			if size != 0 && len(rows.Rows)%size != 0 {
+				return 0, NewMessageTruncatedError("packet does not contain an integral number of rows")
+			}
+			if bytesAvailable < len(rows.Rows) {
+				return 0, NewMessageTruncatedError(fmt.Sprintf("not enough space for attribute: %v", attr.Name))
+			}
+			bytes, err := b.AppendBytes(len(rows.Rows))
+			if err != nil {
+				return 0, err
+			}
+			copy(bytes, rows.Rows)
+			return len(rows.Rows), nil
+		}
+		return 0, errors.New("unexpected type for table serialization")
 	}
 	size := attr.GetSize()
 	if bytesAvailable < size {
@@ -774,3 +812,25 @@
 	}
 	return err
 }
+
+// AttributeValueMapBufferSize will determine how much space is needed to encode all
+// of the attributes
+func AttributeValueMapBufferSize(classID ClassID, attributes AttributeValueMap, msgType uint8) (int, error) {
+	attrDefs, err := GetAttributesDefinitions(classID)
+	if err.StatusCode() != Success {
+		return 0, err
+	} else if attributes == nil {
+		return 0, NewProcessingError("Invalid (nil) Attribute Value Map referenced")
+	}
+	bufferSize := 0
+	isGetResponse := msgType == 0x29
+
+	for _, attrDef := range attrDefs {
+		if isGetResponse && attrDef.IsTableAttribute() {
+			bufferSize += 4
+		} else {
+			bufferSize += attrDef.GetSize()
+		}
+	}
+	return bufferSize, nil
+}
diff --git a/generated/attributeme.go b/generated/attributeme.go
index 80f4e30..43d73da 100644
--- a/generated/attributeme.go
+++ b/generated/attributeme.go
@@ -27,11 +27,11 @@
 
 // AttributeMeClassID is the 16-bit ID for the OMCI
 // Managed entity Attribute ME
-const AttributeMeClassID ClassID = ClassID(289)
+const AttributeMeClassID = ClassID(289) // 0x0121
 
 var attributemeBME *ManagedEntityDefinition
 
-// AttributeMe (class ID #289)
+// AttributeMe (Class ID: #289 / 0x0121)
 //	This ME describes a particular attribute type that is supported by the ONU. This ME is not
 //	included in an MIB upload.
 //
@@ -41,48 +41,90 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. This number is
-//			the same as the one that appears in the attributes table in the ME. Only one instance of each
-//			unique attribute need be created. The ONU can assign attribute numbering as it pleases, out of
-//			the pool of 64K IDs; however, it is suggested that the numbering follow a rational scheme to aid
-//			human readability. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. This number is the same as the one
+//			that appears in the attributes table in the ME. Only one instance of each unique attribute need
+//			be created. The ONU can assign attribute numbering as it pleases, out of the pool of 64K IDs;
+//			however, it is suggested that the numbering follow a rational scheme to aid human readability.
+//			(R) (mandatory) (2-bytes)
 //
 //		Name
-//			Name:	This attribute contains a 25-byte mnemonic tag for the attribute. Strings shorter than
-//			25-bytes are padded with null characters. (R) (mandatory) (25-bytes)
+//			This attribute contains a 25-byte mnemonic tag for the attribute. Strings shorter than 25-bytes
+//			are padded with null characters. (R) (mandatory) (25-bytes)
 //
 //		Size
-//			Size:	This attribute contains the size of the attribute, in bytes. The value 0 indicates that
-//			the attribute can have a variable/unknown size. (R) (mandatory) (2-bytes)
+//			This attribute contains the size of the attribute, in bytes. The value 0 indicates that the
+//			attribute can have a variable/unknown size. (R) (mandatory) (2-bytes)
 //
 //		Access
+//			This attribute represents the OMCI access characteristics of the attribute. The following code
+//			points are defined.
+//
+//			1	Read
+//
+//			2	Write
+//
+//			3	Read, write
+//
+//			5	Read, setbycreate
+//
+//			6	Write, setbycreate
+//
+//			7	Read, write, setbycreate
+//
 //			(R) (mandatory) (1-byte)
 //
 //		Format
+//			This attribute represents the format of the attribute. The following code points are defined.
+//
+//			1	Pointer
+//
+//			2	Bit field
+//
+//			3	Signed integer
+//
+//			4	Unsigned integer
+//
+//			5	String
+//
+//			6	Enumeration (that is, a set of defined code points)
+//
+//			7	Table
+//
 //			(R) (mandatory) (1-byte)
 //
 //		Lower Limit
-//			Lower limit:	This attribute provides the lowest value for the attribute. Valid for numeric types
-//			(pointer, signed integer, unsigned integer) only. For attributes smaller than 4-bytes, the
-//			desired numeric value is expressed in 4-byte representation (for example, the 2s complement
-//			1-byte integer 0xFE is expressed as 0xFFFF-FFFE; the unsigned 1-byte integer 0xFE is expressed
-//			as 0x0000-00FE). (R) (mandatory) (4-bytes)
+//			This attribute provides the lowest value for the attribute. Valid for numeric types (pointer,
+//			signed integer, unsigned integer) only. For attributes smaller than 4-bytes, the desired numeric
+//			value is expressed in 4-byte representation (for example, the 2s complement 1-byte integer 0xFE
+//			is expressed as 0xFFFF-FFFE; the unsigned 1-byte integer 0xFE is expressed as 0x0000-00FE). (R)
+//			(mandatory) (4-bytes)
 //
 //		Upper Limit
-//			Upper limit:	This attribute provides the highest value for the attribute. It has the same
-//			validity and format as the lower limit attribute. (R) (mandatory) (4-bytes)
+//			This attribute provides the highest value for the attribute. It has the same validity and format
+//			as the lower limit attribute. (R) (mandatory) (4-bytes)
 //
 //		Bit Field
-//			Bit field:	This attribute is a mask of the supported bits in a bit field attribute, valid for
-//			bit field type only. A 1 in any position signifies that its code point is supported, while 0
-//			indicates that it is not supported. For bit fields smaller than 4-bytes, the attribute is
-//			aligned at the least significant end of the mask. (R) (mandatory) (4-bytes)
+//			This attribute is a mask of the supported bits in a bit field attribute, valid for bit field
+//			type only. A 1 in any position signifies that its code point is supported, while 0 indicates
+//			that it is not supported. For bit fields smaller than 4-bytes, the attribute is aligned at the
+//			least significant end of the mask. (R) (mandatory) (4-bytes)
 //
 //		Code Points Table
-//			Code points table: This attribute lists the code points supported by an enumerated attribute.
-//			(R) (mandatory) (2 * Q bytes, where Q is the number of entries in the table.)
+//			This attribute lists the code points supported by an enumerated attribute. (R) (mandatory) (2 *
+//			Q bytes, where Q is the number of entries in the table.)
 //
 //		Support
+//			This attribute represents the level of support of the attribute (same notation as the attribute
+//			of the same name in the ME). The following code points are defined.
+//
+//			1	Fully supported (supported as defined in this object)
+//
+//			2	Unsupported (OMCI returns an error code if accessed)
+//
+//			3	Partially supported (some aspects of attribute supported)
+//
+//			4	Ignored (OMCI supported, but underlying function is not)
+//
 //			(R) (mandatory) (1-byte)
 //
 type AttributeMe struct {
diff --git a/generated/authenticationsecuritymethod.go b/generated/authenticationsecuritymethod.go
index 57eb10d..fd1eb1b 100644
--- a/generated/authenticationsecuritymethod.go
+++ b/generated/authenticationsecuritymethod.go
@@ -27,11 +27,11 @@
 
 // AuthenticationSecurityMethodClassID is the 16-bit ID for the OMCI
 // Managed entity Authentication security method
-const AuthenticationSecurityMethodClassID ClassID = ClassID(148)
+const AuthenticationSecurityMethodClassID = ClassID(148) // 0x0094
 
 var authenticationsecuritymethodBME *ManagedEntityDefinition
 
-// AuthenticationSecurityMethod (class ID #148)
+// AuthenticationSecurityMethod (Class ID: #148 / 0x0094)
 //	The authentication security method defines the user ID and password configuration to establish a
 //	session between a client and a server. This object may be used in the role of the client or
 //	server. An instance of this ME is created by the OLT if authenticated communication is
@@ -43,25 +43,37 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The value 0xFFFF
-//			is reserved. (R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. The value 0xFFFF is reserved. (R,
+//			setbycreate) (mandatory) (2-bytes)
 //
 //		Validation Scheme
+//			This attribute specifies the validation scheme used when the ONU validates a challenge.
+//			Validation schemes are defined as follows.
+//
+//			0	Validation disabled
+//
+//			1	Validate using MD5 digest authentication as defined in [IETF-RFC-2617] (recommended)
+//
+//			3	Validate using basic authentication as defined in [IETF RFC 2617]
+//
 //			(R,-W) (mandatory) (1-byte)
 //
 //		Username 1
-//			Username 1:	This string attribute is the user name. If the string is shorter than 25-bytes, it
-//			must be null terminated (Note). (R,-W) (mandatory) (25-bytes)
+//			This string attribute is the user name. If the string is shorter than 25-bytes, it must be null
+//			terminated (Note). (R,-W) (mandatory) (25-bytes)
 //
 //		Password
-//			Password:	This string attribute is the password. If the string is shorter than 25-bytes, it must
-//			be null terminated. (R,-W) (mandatory) (25-bytes)
+//			This string attribute is the password. If the string is shorter than 25-bytes, it must be null
+//			terminated. (R,-W) (mandatory) (25-bytes)
 //
 //		Realm
-//			Realm:	This string attribute specifies the realm used in digest authentication. If the string is
+//			This string attribute specifies the realm used in digest authentication. If the string is
 //			shorter than 25-bytes, it must be null terminated. (R,-W) (mandatory) (25-bytes)
 //
 //		Username 2
+//			This string attribute allows for continuation of the user name beyond 25-characters (Note). Its
+//			default value is a null string. (R,-W) (optional) (25-bytes)
+//
 //			NOTE - The total username is the concatenation of the username 1 and username 2 attributes if
 //			and only if: a) username 1 comprises 25 non-null characters; b) username 2 is supported by the
 //			ONU; and c) username 2 contains a leading non-null character string. Otherwise, the total
diff --git a/generated/bbftr-069managementserver.go b/generated/bbftr-069managementserver.go
index 46a098e..6aab0a9 100644
--- a/generated/bbftr-069managementserver.go
+++ b/generated/bbftr-069managementserver.go
@@ -27,11 +27,11 @@
 
 // BbfTr069ManagementServerClassID is the 16-bit ID for the OMCI
 // Managed entity BBF TR-069 management server
-const BbfTr069ManagementServerClassID ClassID = ClassID(340)
+const BbfTr069ManagementServerClassID = ClassID(340) // 0x0154
 
 var bbftr069managementserverBME *ManagedEntityDefinition
 
-// BbfTr069ManagementServer (class ID #340)
+// BbfTr069ManagementServer (Class ID: #340 / 0x0154)
 //	If functions within the ONU are managed by [BBF TR-069], this ME allows OMCI configuration of
 //	the autoconfiguration server (ACS) URL and related authentication information for an ACS
 //	connection initiated by the ONU. [BBF TR-069] supports other means to discover its ACS, so not
@@ -47,25 +47,25 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of a VEIP that links to the BBF TR-069
-//			management domain. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of a VEIP that links to the BBF TR-069 management domain. (R)
+//			(mandatory) (2-bytes)
 //
 //		Administrative State
-//			Administrative state: This attribute locks (1) and unlocks (0) the functions performed by this
-//			ME. When the administrative state is locked, the functions of this ME are disabled. BBF TR-069
-//			connectivity to an ACS may be possible through means that do not depend on this ME. The default
-//			value of this attribute is locked. (R,W) (mandatory) (1-byte)
+//			This attribute locks (1) and unlocks (0) the functions performed by this ME. When the
+//			administrative state is locked, the functions of this ME are disabled. BBF TR-069 connectivity
+//			to an ACS may be possible through means that do not depend on this ME. The default value of this
+//			attribute is locked. (R,W) (mandatory) (1-byte)
 //
 //		Acs Network Address
-//			ACS network address: This attribute points to an instance of a network address ME that contains
-//			URL and authentication information associated with the ACS URL. (R, W) (mandatory) (2 bytes)
+//			This attribute points to an instance of a network address ME that contains URL and
+//			authentication information associated with the ACS URL. (R, W) (mandatory) (2 bytes)
 //
 //		Associated Tag
-//			Associated tag: This attribute is a TCI value for BBF TR-069 management traffic passing through
-//			the VEIP. A TCI, comprising user priority, CFI and VID, is represented by 2-bytes. The value
-//			0xFFFF specifies that BBF TR-069 management traffic passes through the VEIP with neither a VLAN
-//			nor a priority tag. (R, W) (mandatory) (2-bytes)
+//			This attribute is a TCI value for BBF TR-069 management traffic passing through the VEIP. A TCI,
+//			comprising user priority, CFI and VID, is represented by 2-bytes. The value 0xFFFF specifies
+//			that BBF TR-069 management traffic passes through the VEIP with neither a VLAN nor a priority
+//			tag. (R, W) (mandatory) (2-bytes)
 //
 type BbfTr069ManagementServer struct {
 	ManagedEntityDefinition
diff --git a/generated/callcontrolperformancemonitoringhistorydata.go b/generated/callcontrolperformancemonitoringhistorydata.go
index 5ef2495..d901177 100644
--- a/generated/callcontrolperformancemonitoringhistorydata.go
+++ b/generated/callcontrolperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // CallControlPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity Call control performance monitoring history data
-const CallControlPerformanceMonitoringHistoryDataClassID ClassID = ClassID(140)
+const CallControlPerformanceMonitoringHistoryDataClassID = ClassID(140) // 0x008c
 
 var callcontrolperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// CallControlPerformanceMonitoringHistoryData (class ID #140)
+// CallControlPerformanceMonitoringHistoryData (Class ID: #140 / 0x008c)
 //	This ME collects PM data related to the call control channel. Instances of this ME are created
 //	and deleted by the OLT.
 //
@@ -42,13 +42,11 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP POTS UNI. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP POTS UNI. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -56,22 +54,21 @@
 //			data 2 ME is optional. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Call Setup Failures
-//			Call setup failures: This attribute counts call set-up failures. (R) (mandatory) (4-bytes)
+//			This attribute counts call set-up failures. (R) (mandatory) (4-bytes)
 //
 //		Call Setup Timer
-//			Call setup timer: This attribute is a high water-mark that records the longest duration of a
-//			single call set-up detected during this interval. Time is measured in milliseconds from the time
-//			an initial set-up was requested by the subscriber until the time at which a response was
-//			provided to the subscriber in the form of busy tone, audible ring tone, etc. (R) (mandatory)
-//			(4-bytes)
+//			This attribute is a high water-mark that records the longest duration of a single call set-up
+//			detected during this interval. Time is measured in milliseconds from the time an initial set-up
+//			was requested by the subscriber until the time at which a response was provided to the
+//			subscriber in the form of busy tone, audible ring tone, etc. (R) (mandatory) (4-bytes)
 //
 //		Call Terminate Failures
-//			Call terminate failures: This attribute counts the number of calls that were terminated with
-//			cause. (R) (mandatory) (4-bytes)
+//			This attribute counts the number of calls that were terminated with cause. (R) (mandatory)
+//			(4-bytes)
 //
 //		Analog Port Releases
-//			Analog port releases: This attribute counts the number of analogue port releases without
-//			dialling detected (abandoned calls). (R) (mandatory) (4-bytes)
+//			This attribute counts the number of analogue port releases without dialling detected (abandoned
+//			calls). (R) (mandatory) (4-bytes)
 //
 //		Analog Port Off_Hook Timer
 //			Analog port off-hook timer: This attribute is a high water-mark that records the longest period
diff --git a/generated/cardholder.go b/generated/cardholder.go
index 0bd413f..5b996c6 100644
--- a/generated/cardholder.go
+++ b/generated/cardholder.go
@@ -27,11 +27,11 @@
 
 // CardholderClassID is the 16-bit ID for the OMCI
 // Managed entity Cardholder
-const CardholderClassID ClassID = ClassID(5)
+const CardholderClassID = ClassID(5) // 0x0005
 
 var cardholderBME *ManagedEntityDefinition
 
-// Cardholder (class ID #5)
+// Cardholder (Class ID: #5 / 0x0005)
 //	The cardholder represents the fixed equipment slot configuration of the ONU. Each cardholder can
 //	contain 0 or 1 circuit packs; the circuit pack models equipment information that can change over
 //	the lifetime of the ONU, e.g., through replacement.
@@ -75,12 +75,32 @@
 //			NOTE 1 - Some xDSL MEs use the two MSBs of the slot number for other purposes. An ONU that
 //			supports these services may have slot limitations or restrictions.
 //
+//			This attribute uniquely identifies each instance of this ME. The ONU sets the first byte of this
+//			2-byte identifier to:
+//
+//			0	if the ONU contains pluggable equipment modules
+//
+//			1	if the ONU is a single piece of integrated equipment.
+//
+//			The second byte of this identifier is the slot number. In integrated ONUs, this byte may be used
+//			as a virtual slot or set to 0 to indicate a universal pseudoslot.
+//
+//			Slot numbering schemes differ among vendors. It is only required that slot numbers be unique
+//			across the ONU. Up to 254 equipment slots are supported in the range 1..254 (Note 1). The value
+//			0 is reserved for possible use in an integrated ONU to indicate a universal pseudo-slot. The
+//			value 255 is also reserved. (R) (mandatory) (2-bytes)
+//
 //		Actual Plug In Unit Type
 //			Actual plugin unit type: This attribute is equal to the type of the circuit pack in the
 //			cardholder, or 0 if the cardholder is empty. When the cardholder is populated, this attribute is
 //			the same as the type attribute of the corresponding circuit pack ME. Circuit pack types are
 //			defined in Table 9.1.5-1. (R) (mandatory) (1-byte)
 //
+//			The three following attributes permit the OLT to specify its intentions for any future equipped
+//			configuration of a slot. Once some or all of these are set, the ONU can proceed to instantiate
+//			circuit pack and PPTP MEs, along with other predeterminable MEs, and allow the OLT to create
+//			related discretionary MEs, thereby supporting service pre-provisioning.
+//
 //		Expected Plug_In Unit Type
 //			Expected plug-in unit type: This attribute provisions the type of circuit pack for the slot. For
 //			type coding, see Table 9.1.5-1. The value 0 means that the cardholder is not provisioned to
@@ -89,29 +109,46 @@
 //			attribute may be used to represent the type of interface. (R,-W) (mandatory) (1-byte)
 //
 //		Expected Port Count
-//			Expected port count: This attribute permits the OLT to specify the number of ports it expects in
-//			a circuit pack. Prior to provisioning by the OLT, the ONU initializes this attribute to 0.
-//			(R,-W) (optional) (1-byte)
+//			This attribute permits the OLT to specify the number of ports it expects in a circuit pack.
+//			Prior to provisioning by the OLT, the ONU initializes this attribute to 0. (R,-W) (optional)
+//			(1-byte)
 //
 //		Expected Equipment Id
-//			Expected equipment ID: This attribute provisions the specific type of expected circuit pack.
-//			This attribute applies only to ONUs that do not have integrated interfaces. In some
-//			environments, this may contain the expected CLEI code. Upon ME instantiation, the ONU sets this
-//			attribute to all spaces. (R,-W) (optional) (20-bytes)
+//			This attribute provisions the specific type of expected circuit pack. This attribute applies
+//			only to ONUs that do not have integrated interfaces. In some environments, this may contain the
+//			expected CLEI code. Upon ME instantiation, the ONU sets this attribute to all spaces. (R,-W)
+//			(optional) (20-bytes)
 //
 //		Actual Equipment Id
-//			Actual equipment ID: This attribute identifies the specific type of circuit pack, once it is
-//			installed. This attribute applies only to ONUs that do not have integrated interfaces. In some
-//			environments, this may include the CLEI code. When the slot is empty or the equipment ID is not
-//			known, this attribute should be set to all spaces. (R) (optional) (20-bytes)
+//			This attribute identifies the specific type of circuit pack, once it is installed. This
+//			attribute applies only to ONUs that do not have integrated interfaces. In some environments,
+//			this may include the CLEI code. When the slot is empty or the equipment ID is not known, this
+//			attribute should be set to all spaces. (R) (optional) (20-bytes)
 //
 //		Protection Profile Pointer
-//			Protection profile pointer: This attribute specifies an equipment protection profile that may be
-//			associated with the cardholder. Its value is the least significant byte of the ME ID of the
-//			equipment protection profile with which it is associated, or 0 if equipment protection is not
-//			used. (R) (optional) (1-byte)
+//			This attribute specifies an equipment protection profile that may be associated with the
+//			cardholder. Its value is the least significant byte of the ME ID of the equipment protection
+//			profile with which it is associated, or 0 if equipment protection is not used. (R) (optional)
+//			(1-byte)
 //
 //		Invoke Protection Switch
+//			The OLT may use this attribute to control equipment protection switching. Code points have the
+//			following meaning when set by the OLT:
+//
+//			0	Release protection switch
+//
+//			1	Operate protection switch, protect cardholder unspecified
+//
+//			2	Operate protection switch, use first protect cardholder
+//
+//			3	Operate protection switch, use second protect cardholder
+//
+//			The ONU should deny attempts to switch to an unequipped, defective or already active protection
+//			cardholder.
+//
+//			Upon the get action from the OLT, this attribute should return the current value of the actual
+//			protection configuration. Code points are as defined above; the value 1 is never returned.
+//
 //			When circuit packs that support a PON interface (IF) function are switched, the response should
 //			be returned on the same PON that received the command. However, the OLT should also be prepared
 //			to accept a response on the redundant PON. (R,-W) (optional) (1-byte)
@@ -120,7 +157,7 @@
 //			Alarm-reporting control (ARC): See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Arc Interval
-//			ARC interval: See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 type Cardholder struct {
 	ManagedEntityDefinition
diff --git a/generated/cesserviceprofile.go b/generated/cesserviceprofile.go
index aebe6b5..ad20760 100644
--- a/generated/cesserviceprofile.go
+++ b/generated/cesserviceprofile.go
@@ -27,11 +27,11 @@
 
 // CesServiceProfileClassID is the 16-bit ID for the OMCI
 // Managed entity CES service profile
-const CesServiceProfileClassID ClassID = ClassID(21)
+const CesServiceProfileClassID = ClassID(21) // 0x0015
 
 var cesserviceprofileBME *ManagedEntityDefinition
 
-// CesServiceProfile (class ID #21)
+// CesServiceProfile (Class ID: #21 / 0x0015)
 //	NOTE - In [ITU-T G.984.4], this ME is called a CES service profile-G.
 //
 //	An instance of this ME organizes data that describe the CES service functions of the ONU.
@@ -42,16 +42,29 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
-//
-//		Ces Buffered Cdv Tolerance
-//			CES buffered CDV tolerance: This attribute represents the duration of user data that must be
-//			buffered by the CES IW entity to offset packet delay variation. It is expressed in 10-us
-//			increments. 75 (750-vs) is suggested as a default value. (R,-W, setbycreate) (mandatory)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
 //			(2-bytes)
 //
+//		Ces Buffered Cdv Tolerance
+//			This attribute represents the duration of user data that must be buffered by the CES IW entity
+//			to offset packet delay variation. It is expressed in 10-us increments. 75 (750-vs) is suggested
+//			as a default value. (R,-W, setbycreate) (mandatory) (2-bytes)
+//
 //		Channel Associated Signalling Cas
+//			Channel associated signalling (CAS): This attribute selects the signalling format. It applies to
+//			structured interfaces only. For unstructured interfaces, this value, if present, must be set to
+//			the default 0. Valid values are as follows.
+//
+//			0	Basic
+//
+//			1	E1 CAS
+//
+//			2	SF CAS
+//
+//			3	DS1 ESF CAS
+//
+//			4	J2 CAS
+//
 //			(R,-W, setbycreate) (optional) (1-byte)
 //
 type CesServiceProfile struct {
diff --git a/generated/circuitpack.go b/generated/circuitpack.go
index e40e29a..0fa6a4e 100644
--- a/generated/circuitpack.go
+++ b/generated/circuitpack.go
@@ -27,11 +27,11 @@
 
 // CircuitPackClassID is the 16-bit ID for the OMCI
 // Managed entity Circuit pack
-const CircuitPackClassID ClassID = ClassID(6)
+const CircuitPackClassID = ClassID(6) // 0x0006
 
 var circuitpackBME *ManagedEntityDefinition
 
-// CircuitPack (class ID #6)
+// CircuitPack (Class ID: #6 / 0x0006)
 //	This ME models a real or virtual circuit pack that is equipped in a real or virtual ONU slot.
 //	For ONUs with integrated interfaces, this ME may be used to distinguish available types of
 //	interfaces (the port-mapping package is another way).
@@ -59,63 +59,76 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Its value is the
-//			same as that of the cardholder ME containing this circuit pack instance. (R, setbycreate if
-//			applicable) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Its value is the same as that of
+//			the cardholder ME containing this circuit pack instance. (R, setbycreate if applicable)
+//			(mandatory) (2-bytes)
 //
 //		Type
-//			Type:	This attribute identifies the circuit pack type. This attribute is a code as defined in
-//			Table 9.1.5-1. The value 255 means unknown or undefined, i.e., the inserted circuit pack is not
+//			This attribute identifies the circuit pack type. This attribute is a code as defined in Table
+//			9.1.5-1. The value 255 means unknown or undefined, i.e., the inserted circuit pack is not
 //			recognized by the ONU or is not mapped to an entry in Table 9.1.5-1. In the latter case, the
 //			equipment ID attribute may contain inventory information. Upon autonomous ME instantiation, the
 //			ONU sets this attribute to 0 or to the type of the circuit pack that is physically present. (R,
 //			setbycreate if applicable) (mandatory) (1-byte)
 //
 //		Number Of Ports
-//			Number of ports: This attribute is the number of access ports on the circuit pack. If the port-
-//			mapping package is supported for this circuit pack, this attribute should be set to the total
-//			number of ports of all types. (R) (optional) (1-byte)
+//			This attribute is the number of access ports on the circuit pack. If the port-mapping package is
+//			supported for this circuit pack, this attribute should be set to the total number of ports of
+//			all types. (R) (optional) (1-byte)
 //
 //		Serial Number
-//			Serial number: The serial number is expected to be unique for each circuit pack, at least within
-//			the scope of the given vendor. Note that the serial number may contain the vendor ID or version
-//			number. For integrated ONUs, this value is identical to the value of the serial number attribute
-//			of the ONU-G ME. Upon creation in the absence of a physical circuit pack, this attribute
-//			comprises all spaces. (R) (mandatory) (8-bytes)
+//			The serial number is expected to be unique for each circuit pack, at least within the scope of
+//			the given vendor. Note that the serial number may contain the vendor ID or version number. For
+//			integrated ONUs, this value is identical to the value of the serial number attribute of the
+//			ONU-G ME. Upon creation in the absence of a physical circuit pack, this attribute comprises all
+//			spaces. (R) (mandatory) (8-bytes)
 //
 //		Version
-//			Version:	This attribute is a string that identifies the version of the circuit pack as defined
-//			by the vendor. The value 0 indicates that version information is not available or applicable.
-//			For integrated ONUs, this value is identical to the value of the version attribute of the ONU-G
-//			ME. Upon creation in the absence of a physical circuit pack, this attribute comprises all
-//			spaces. (R) (mandatory) (14-bytes)
+//			This attribute is a string that identifies the version of the circuit pack as defined by the
+//			vendor. The value 0 indicates that version information is not available or applicable. For
+//			integrated ONUs, this value is identical to the value of the version attribute of the ONU-G ME.
+//			Upon creation in the absence of a physical circuit pack, this attribute comprises all spaces.
+//			(R) (mandatory) (14-bytes)
 //
 //		Vendor Id
-//			Vendor ID:	This attribute identifies the vendor of the circuit pack. For ONUs with integrated
-//			interfaces, this value is identical to the value of the vendor ID attribute of the ONU-G ME.
-//			Upon creation in the absence of a physical circuit pack, this attribute comprises all spaces.
-//			(R) (optional) (4-bytes)
+//			This attribute identifies the vendor of the circuit pack. For ONUs with integrated interfaces,
+//			this value is identical to the value of the vendor ID attribute of the ONU-G ME. Upon creation
+//			in the absence of a physical circuit pack, this attribute comprises all spaces. (R) (optional)
+//			(4-bytes)
 //
 //		Administrative State
-//			Administrative state: This attribute locks (1) and unlocks (0) the functions performed by this
-//			ME. Administrative state is further described in clause A.1.6. (R,-W) (mandatory) (1-byte)
+//			This attribute locks (1) and unlocks (0) the functions performed by this ME. Administrative
+//			state is further described in clause A.1.6. (R,-W) (mandatory) (1-byte)
 //
 //		Operational State
-//			Operational state: This attribute indicates whether the circuit pack is capable of performing
-//			its function. Valid values are enabled (0), disabled (1) and unknown (2). Pending completion of
-//			initialization and self-test on an installed circuit pack, the ONU sets this attribute to 2. (R)
-//			(optional) (1-byte)
+//			This attribute indicates whether the circuit pack is capable of performing its function. Valid
+//			values are enabled (0), disabled (1) and unknown (2). Pending completion of initialization and
+//			self-test on an installed circuit pack, the ONU sets this attribute to 2. (R) (optional)
+//			(1-byte)
 //
 //		Bridged Or Ip Ind
+//			This attribute specifies whether an Ethernet interface is bridged or derived from an IP router
+//			function.
+//
+//			0	Bridged
+//
+//			1	IP router
+//
+//			2	Both bridged and IP router functions
+//
 //			(R,-W) (optional, only applicable for circuit packs with Ethernet interfaces) (1-byte)
 //
 //		Equipment Id
-//			Equipment ID: This attribute may be used to identify the vendor's specific type of circuit pack.
-//			In some environments, this attribute may include the CLEI code. Upon ME instantiation, the ONU
-//			sets this attribute to all spaces or to the equipment ID of the circuit pack that is physically
-//			present. (R) (optional) (20-bytes)
+//			This attribute may be used to identify the vendor's specific type of circuit pack. In some
+//			environments, this attribute may include the CLEI code. Upon ME instantiation, the ONU sets this
+//			attribute to all spaces or to the equipment ID of the circuit pack that is physically present.
+//			(R) (optional) (20-bytes)
 //
 //		Card Configuration
+//			This attribute selects the appropriate configuration of configurable circuit packs. Table
+//			9.1.5-1 specifies two configurable card types: C-DS1/E1 (code 16), and C-DS1/E1/J1 (code 17).
+//			Values are indicated below for the allowed card types and configurations.
+//
 //			Upon autonomous instantiation, this attribute is set to 0. (R,-W, setbycreate if applicable)
 //			(mandatory for configurable circuit packs) (1-byte)
 //
@@ -126,26 +139,24 @@
 //			scheduler function) (1-byte)
 //
 //		Total Priority Queue Number
-//			Total priority queue number: This value reports the total number of priority queues associated
-//			with the circuit pack. Upon ME instantiation, the ONU sets the attribute to 0 or to the value
-//			supported by the physical circuit pack. (R) (mandatory for circuit packs that provide a traffic
-//			scheduler function) (1-byte)
+//			This value reports the total number of priority queues associated with the circuit pack. Upon ME
+//			instantiation, the ONU sets the attribute to 0 or to the value supported by the physical circuit
+//			pack. (R) (mandatory for circuit packs that provide a traffic scheduler function) (1-byte)
 //
 //		Total Traffic Scheduler Number
-//			Total traffic scheduler number: This value reports the total number of traffic schedulers
-//			associated with the circuit pack. The ONU supports null function, strict priority scheduling and
-//			WRR from the priority control, and guarantee of minimum rate control points of view. If the
-//			circuit pack has no traffic scheduler, this attribute should be absent or have the value 0. Upon
-//			ME instantiation, the ONU sets the attribute to 0 or to the value supported by the physical
-//			circuit pack. (R) (mandatory for circuit packs that provide a traffic scheduler function)
-//			(1-byte)
+//			This value reports the total number of traffic schedulers associated with the circuit pack. The
+//			ONU supports null function, strict priority scheduling and WRR from the priority control, and
+//			guarantee of minimum rate control points of view. If the circuit pack has no traffic scheduler,
+//			this attribute should be absent or have the value 0. Upon ME instantiation, the ONU sets the
+//			attribute to 0 or to the value supported by the physical circuit pack. (R) (mandatory for
+//			circuit packs that provide a traffic scheduler function) (1-byte)
 //
 //		Power Shed Override
-//			Power shed override: This attribute allows ports to be excluded from the power shed control
-//			defined in clause 9.1.7. It is a bit mask that takes port 1 as the MSB; a bit value of 1 marks
-//			the corresponding port to override the power shed timer. For hardware that cannot shed power per
-//			port, this attribute is a slot override rather than a port override, with any non-zero port
-//			value causing the entire circuit pack to override power shedding. (R,-W) (optional) (4-bytes)
+//			This attribute allows ports to be excluded from the power shed control defined in clause 9.1.7.
+//			It is a bit mask that takes port 1 as the MSB; a bit value of 1 marks the corresponding port to
+//			override the power shed timer. For hardware that cannot shed power per port, this attribute is a
+//			slot override rather than a port override, with any non-zero port value causing the entire
+//			circuit pack to override power shedding. (R,-W) (optional) (4-bytes)
 //
 type CircuitPack struct {
 	ManagedEntityDefinition
@@ -157,9 +168,10 @@
 		Name:    "CircuitPack",
 		ClassID: 6,
 		MessageTypes: mapset.NewSetWith(
-			Create,
 			Get,
 			Set,
+			Create,
+			Delete,
 		),
 		AllowedAttributeMask: 0xfffc,
 		AttributeDefinitions: AttributeDefinitionMap{
@@ -179,7 +191,7 @@
 			13: ByteField("TotalTrafficSchedulerNumber", UnsignedIntegerAttributeType, 0x0008, 0, mapset.NewSetWith(Read), false, false, false, 13),
 			14: Uint32Field("PowerShedOverride", BitFieldAttributeType, 0x0004, 0, mapset.NewSetWith(Read, Write), false, true, false, 14),
 		},
-		Access:  CreatedByOlt,
+		Access:  CreatedByOnu,
 		Support: UnknownSupport,
 		Alarms: AlarmMap{
 			0: "Equipment alarm",
diff --git a/generated/classidmap.go b/generated/classidmap.go
index 71abb89..eef38d7 100644
--- a/generated/classidmap.go
+++ b/generated/classidmap.go
@@ -53,7 +53,7 @@
 
 func init() {
 	// Create mapping of 16-bit managed entity class IDs to ME-type
-	classToManagedEntityMap = make(map[ClassID]CreateME, 179)
+	classToManagedEntityMap = make(map[ClassID]CreateME, 193)
 
 	classToManagedEntityMap[2] = NewOnuData
 	classToManagedEntityMap[5] = NewCardholder
@@ -120,15 +120,21 @@
 	classToManagedEntityMap[146] = NewVoipApplicationServiceProfile
 	classToManagedEntityMap[147] = NewVoipFeatureAccessCodes
 	classToManagedEntityMap[148] = NewAuthenticationSecurityMethod
+	classToManagedEntityMap[149] = NewSipConfigPortal
 	classToManagedEntityMap[150] = NewSipAgentConfigData
 	classToManagedEntityMap[151] = NewSipAgentPerformanceMonitoringHistoryData
 	classToManagedEntityMap[152] = NewSipCallInitiationPerformanceMonitoringHistoryData
 	classToManagedEntityMap[153] = NewSipUserData
+	classToManagedEntityMap[154] = NewMgcConfigPortal
 	classToManagedEntityMap[155] = NewMgcConfigData
 	classToManagedEntityMap[156] = NewMgcPerformanceMonitoringHistoryData
+	classToManagedEntityMap[157] = NewLargeString
+	classToManagedEntityMap[158] = NewOnuRemoteDebug
 	classToManagedEntityMap[160] = NewEquipmentExtensionPackage
 	classToManagedEntityMap[162] = NewPhysicalPathTerminationPointMocaUni
 	classToManagedEntityMap[163] = NewMocaEthernetPerformanceMonitoringHistoryData
+	classToManagedEntityMap[164] = NewMocaInterfacePerformanceMonitoringHistoryData
+	classToManagedEntityMap[165] = NewVdsl2LineConfigurationExtensions
 	classToManagedEntityMap[168] = NewVdsl2LineInventoryAndStatusDataPart1
 	classToManagedEntityMap[169] = NewVdsl2LineInventoryAndStatusDataPart2
 	classToManagedEntityMap[170] = NewVdsl2LineInventoryAndStatusDataPart3
@@ -203,11 +209,14 @@
 	classToManagedEntityMap[346] = NewXgPonUpstreamManagementPerformanceMonitoringHistoryData
 	classToManagedEntityMap[348] = NewMacBridgePortIcmpv6ProcessPreAssignTable
 	classToManagedEntityMap[400] = NewEthernetPseudowireParameters
+	classToManagedEntityMap[406] = NewEponDownstreamPerformanceMonitoringConfiguration
+	classToManagedEntityMap[407] = NewSipAgentConfigData2
 	classToManagedEntityMap[408] = NewXdslXtuCPerformanceMonitoringHistoryDataPart2
 	classToManagedEntityMap[410] = NewVdsl2LineConfigurationExtensions3
 	classToManagedEntityMap[412] = NewXdslChannelConfigurationProfilePart2
 	classToManagedEntityMap[413] = NewXtuDataGatheringConfiguration
 	classToManagedEntityMap[414] = NewXdslLineInventoryAndStatusDataPart8
+	classToManagedEntityMap[415] = NewVdsl2LineInventoryAndStatusDataPart4
 	classToManagedEntityMap[418] = NewEfmBondingGroup
 	classToManagedEntityMap[419] = NewEfmBondingLink
 	classToManagedEntityMap[420] = NewEfmBondingGroupPerformanceMonitoringHistoryData
@@ -216,12 +225,15 @@
 	classToManagedEntityMap[423] = NewEfmBondingPortPerformanceMonitoringHistoryData
 	classToManagedEntityMap[424] = NewEfmBondingPortPerformanceMonitoringHistoryDataPart2
 	classToManagedEntityMap[425] = NewEthernetFrameExtendedPm64Bit
+	classToManagedEntityMap[427] = NewPhysicalPathTerminationPointXdslUniPart3
 	classToManagedEntityMap[432] = NewFastChannelConfigurationProfile
 	classToManagedEntityMap[433] = NewFastDataPathConfigurationProfile
 	classToManagedEntityMap[434] = NewFastVectoringLineConfigurationExtensions
 	classToManagedEntityMap[436] = NewFastLineInventoryAndStatusDataPart2
 	classToManagedEntityMap[437] = NewFastXtuCPerformanceMonitoringHistoryData
 	classToManagedEntityMap[438] = NewFastXtuRPerformanceMonitoringHistoryData
+	classToManagedEntityMap[440] = NewTimeStatusMessage
+	classToManagedEntityMap[441] = NewOnu3G
 	classToManagedEntityMap[443] = NewTwdmChannelManagedEntity
 	classToManagedEntityMap[444] = NewTwdmChannelPhyLodsPerformanceMonitoringHistoryData
 	classToManagedEntityMap[445] = NewTwdmChannelXgemPerformanceMonitoringHistoryData
@@ -234,6 +246,8 @@
 	classToManagedEntityMap[452] = NewTwdmChannelOmciPerformanceMonitoringHistoryData
 	classToManagedEntityMap[453] = NewEnhancedFecPerformanceMonitoringHistoryData
 	classToManagedEntityMap[454] = NewEnhancedTcPerformanceMonitoringHistoryData
+	classToManagedEntityMap[456] = NewOnuManufacturingData
+	classToManagedEntityMap[457] = NewOnuTimeConfiguration
 }
 
 // LoadManagedEntityDefinition returns a function to create a Managed Entity for a specific
@@ -274,3 +288,12 @@
 		(ClassID(350) <= classID && classID <= ClassID(399)) ||
 		(ClassID(65280) <= classID && classID <= ClassID(65535))
 }
+
+// IsUnknownClassID returns true if the provided class ID is reserved in ITU-T G.988
+// for vendor specific functionality or is not decoded/supported by this library
+func IsUnknownClassID(classID ClassID) bool {
+	if _, err := LoadManagedEntityDefinition(classID); err != nil {
+		return false
+	}
+	return true
+}
diff --git a/generated/classidmap_test.go b/generated/classidmap_test.go
new file mode 100644
index 0000000..e3dde04
--- /dev/null
+++ b/generated/classidmap_test.go
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+/*
+ * NOTE: This file was generated, manual edits will be overwritten!
+ *
+ * Generated by 'goCodeGenerator.py':
+ *              https://github.com/cboling/OMCI-parser/README.md
+ */
+
+package generated
+
+import (
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+func TestClassIDMap(t *testing.T) {
+	for classID, function := range classToManagedEntityMap {
+		managedEntity, omciError := function()
+
+		assert.NotNil(t, managedEntity)
+		assert.Equal(t, omciError.StatusCode(), Success)
+
+		assert.Equal(t, classID, managedEntity.GetClassID())
+		assert.NotNil(t, managedEntity.GetManagedEntityDefinition())
+	}
+}
diff --git a/generated/classsupport.go b/generated/classsupport.go
index df47014..90b85d9 100644
--- a/generated/classsupport.go
+++ b/generated/classsupport.go
@@ -14,6 +14,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+/*
+ * NOTE: This file was generated, manual edits will be overwritten!
+ *
+ * Generated by 'goCodeGenerator.py':
+ *              https://github.com/cboling/OMCI-parser/README.md
+ */
 
 package generated
 
diff --git a/generated/dot1agcfmstack.go b/generated/dot1agcfmstack.go
index 882a1b1..08dda58 100644
--- a/generated/dot1agcfmstack.go
+++ b/generated/dot1agcfmstack.go
@@ -27,11 +27,11 @@
 
 // Dot1AgCfmStackClassID is the 16-bit ID for the OMCI
 // Managed entity Dot1ag CFM stack
-const Dot1AgCfmStackClassID ClassID = ClassID(305)
+const Dot1AgCfmStackClassID = ClassID(305) // 0x0131
 
 var dot1agcfmstackBME *ManagedEntityDefinition
 
-// Dot1AgCfmStack (class ID #305)
+// Dot1AgCfmStack (Class ID: #305 / 0x0131)
 //	This ME reports the maintenance status of a bridge port at any given time. An ONU that supports
 //	[IEEE 802.1ag] functionality automatically creates an instance of the dot1ag CFM stack ME for
 //	each MAC bridge or IEEE 802.1p mapper, depending on its provisioning model.
@@ -48,20 +48,79 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies an instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the MAC bridge service profile ME
-//			or an IEEE 802.1p mapper ME. It is expected that an ONU will implement CFM on bridges or on
-//			IEEE-802.1p mappers, but not both. For precision, the reference is disambiguated by the value of
-//			the layer 2 type pointer attribute. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies an instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the MAC bridge service profile ME or an IEEE 802.1p mapper
+//			ME. It is expected that an ONU will implement CFM on bridges or on IEEE-802.1p mappers, but not
+//			both. For precision, the reference is disambiguated by the value of the layer 2 type pointer
+//			attribute. (R) (mandatory) (2-bytes)
 //
 //		Layer 2 Type
-//			Layer 2 type:	This attribute specifies whether the dot1ag CFM stack is associated with a MAC
-//			bridge service profile (value 0) or an IEEE 802.1p mapper (value 1). (R) (mandatory) (1-byte)
+//			This attribute specifies whether the dot1ag CFM stack is associated with a MAC bridge service
+//			profile (value 0) or an IEEE 802.1p mapper (value 1). (R) (mandatory) (1-byte)
 //
 //		Mp Status Table
+//			This attribute is a list of entries, each entry reporting one aspect of the maintenance status
+//			of one port. If a port is associated with more than one CFM maintenance entity, each is
+//			represented as a separate item in this table attribute; a port that has no current maintenance
+//			functions is not represented in the table (so the table may be empty). Each entry is defined as
+//			follows.
+//
+//			Port ID: The ME ID of the MAC bridge port config data whose information is reported in this
+//			entry. If the layer 2 parent is an IEEE 802.1p mapper, a null pointer. (2-bytes)
+//
+//			Level: The level at which the reported maintenance function exists, 0..7. (1-byte)
+//
+//			Direction: The value 1 (down) or 2 (up). (1-byte)
+//
+//			VLAN ID: If this table entry reports a maintenance function associated with a VLAN, this field
+//			contains the value of the primary VLAN ID. If no VLAN is associated with this entry, this field
+//			contains the value 0. (2-bytes)
+//
+//			MD: A pointer to the associated dot1ag maintenance domain ME. If no MD is associated with this
+//			entry, a null pointer. (2-bytes)
+//
+//			MA: A pointer to the associated dot1ag maintenance association ME. If no MA is associated with
+//			this entry, a null pointer. (2-bytes)
+//
+//			MEP ID: If this table entry reports an MEP, this field contains the value of its MEP ID (range
+//			1..8191). If this table entry reports an MHF, this field contains the value 0. (2-bytes)
+//
+//			MAC address: The MAC address of the MP. (6-bytes)
+//
 //			(R) (mandatory) (18N bytes)
 //
 //		Configuration Error List Table
+//			This attribute is based on the [IEEE 802.1ag] configuration error list. It is a list of entries,
+//			each entry reporting a VLAN and a bridge port against which a configuration error has been
+//			detected. The table may be empty at any given time. Entries are defined as follows:
+//
+//			VLAN ID: If this table entry reports a maintenance function associated with a VLAN, this field
+//			contains the value of the VLAN ID in error. If no VLAN is associated with this entry, this field
+//			contains the value 0. (2-bytes)
+//
+//			Port ID: A pointer to the MAC bridge port config data whose information is reported in this
+//			entry. If the layer 2 parent is an IEEE 802.1p mapper, a null pointer. (2-bytes)
+//
+//			Detected configuration error: A bit mask with the following meanings. A list entry exists if and
+//			only if at least one of these bits is set. Definitions appear in clause 22.2.4 of [IEEE
+//			802.1ag]: (1-byte)
+//
+//			0x01	CFM leak. MA x is associated with a specific VID list, one or more of the VIDs in MA x can
+//			pass through the bridge port, no up MEP is configured for MA x on the bridge port, no down MEP
+//			is configured on any bridge port for MA x, and another MA y, at a higher MD level than MA x, and
+//			associated with at least one of the VID(s) also in MA x, does have an MEP configured on the
+//			bridge port.
+//
+//			0x02	Conflicting VIDs. MA x is associated with a specific VID list, an up MEP is configured on
+//			MA x on the bridge port, and another MA y, associated with at least one of the VID(s) also in MA
+//			x, and at the same MD level as MA x, also has an up MEP configured on some bridge port.
+//
+//			0x04	Excessive levels. The number of different MD levels at which maintenance domain
+//			intermediate points (MIPs) are to be created on this port exceeds the bridge's capabilities.
+//
+//			0x08	Overlapped levels. An MEP is created for one VID at one MD level, but an MEP is also
+//			configured on another VID at that MD level or higher, exceeding the bridge's capabilities.
+//
 //			(R) (mandatory) (5N bytes)
 //
 type Dot1AgCfmStack struct {
diff --git a/generated/dot1agchassis-managementinfo.go b/generated/dot1agchassis-managementinfo.go
index bfdf25b..75d0106 100644
--- a/generated/dot1agchassis-managementinfo.go
+++ b/generated/dot1agchassis-managementinfo.go
@@ -27,11 +27,11 @@
 
 // Dot1AgChassisManagementInfoClassID is the 16-bit ID for the OMCI
 // Managed entity Dot1ag chassis-management info
-const Dot1AgChassisManagementInfoClassID ClassID = ClassID(306)
+const Dot1AgChassisManagementInfoClassID = ClassID(306) // 0x0132
 
 var dot1agchassismanagementinfoBME *ManagedEntityDefinition
 
-// Dot1AgChassisManagementInfo (class ID #306)
+// Dot1AgChassisManagementInfo (Class ID: #306 / 0x0132)
 //	This ME represents the system-level chassis ID or management address for [IEEE-802.1ag] CFM
 //	messages, and potentially for other IEEE 802-based functions. Although [IEEE-802.1AB] allows for
 //	several management addresses (synonyms in different formats or with granularity to the component
diff --git a/generated/dot1agdefaultmdlevel.go b/generated/dot1agdefaultmdlevel.go
index 2cb7823..0d1e13e 100644
--- a/generated/dot1agdefaultmdlevel.go
+++ b/generated/dot1agdefaultmdlevel.go
@@ -27,11 +27,11 @@
 
 // Dot1AgDefaultMdLevelClassID is the 16-bit ID for the OMCI
 // Managed entity Dot1ag default MD level
-const Dot1AgDefaultMdLevelClassID ClassID = ClassID(301)
+const Dot1AgDefaultMdLevelClassID = ClassID(301) // 0x012d
 
 var dot1agdefaultmdlevelBME *ManagedEntityDefinition
 
-// Dot1AgDefaultMdLevel (class ID #301)
+// Dot1AgDefaultMdLevel (Class ID: #301 / 0x012d)
 //	The collection of the functionality called a maintenance half-function (MHF) is not explicitly
 //	modelled as a ME by either [IEEE 802.1ag] or the OMCI. The ONU automatically creates MHFs
 //	according to parameters specified in a dot1ag MD or a dot1ag MA ME; the dot1ag default MD level
@@ -51,32 +51,100 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies an instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the MAC bridge service profile ME
-//			or an IEEE 802.1p mapper ME. It is expected that an ONU will implement CFM on bridges or on
-//			IEEE-802.1p mappers, but not both, depending on its provisioning model. For precision, the
-//			reference is disambiguated by the value of the layer 2 type pointer attribute. (R) (mandatory)
-//			(2-bytes)
+//			This attribute uniquely identifies an instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the MAC bridge service profile ME or an IEEE 802.1p mapper
+//			ME. It is expected that an ONU will implement CFM on bridges or on IEEE-802.1p mappers, but not
+//			both, depending on its provisioning model. For precision, the reference is disambiguated by the
+//			value of the layer 2 type pointer attribute. (R) (mandatory) (2-bytes)
 //
 //		Layer 2 Type
-//			Layer 2 type: This attribute specifies whether the dot1ag default MD level ME is associated with
-//			a MAC bridge service profile (value 0) or an IEEE 802.1p mapper (value-1). (R) (mandatory)
-//			(1-byte)
+//			This attribute specifies whether the dot1ag default MD level ME is associated with a MAC bridge
+//			service profile (value 0) or an IEEE 802.1p mapper (value-1). (R) (mandatory) (1-byte)
 //
 //		Catchall Level
-//			Catchall level: This attribute ranges from 0..7 and specifies the MD level of MHFs created when
-//			no specific match is found. (R,-W) (mandatory) (1-byte)
+//			This attribute ranges from 0..7 and specifies the MD level of MHFs created when no specific
+//			match is found. (R,-W) (mandatory) (1-byte)
 //
 //		Catchall Mhf Creation
+//			This attribute determines whether, when no more specific match is found, the bridge creates an
+//			MHF or not. This attribute is an enumeration with the following values:
+//
+//			1	None. The bridge does not create any MHFs. This is the default value.
+//
+//			2	Default. The bridge can create MHFs on this VID on any port through which the VID can pass.
+//
+//			3	Explicit. The bridge can create MHFs on this VID on any port through which the VID can pass,
+//			but only if an MEP exists at some lower maintenance level.
+//
 //			(R,-W) (mandatory) (1-byte)
 //
 //		Catchall Sender Id Permission
-//			Catchall sender ID permission: This attribute determines the contents of the sender ID TLV
-//			included in CFM messages transmitted by MPs when no more specific match is found. This attribute
-//			is identical to that defined in the description of the dot1ag MD ME (i.e., excluding code point
-//			5, defer). (R,-W) (mandatory) (1-byte)
+//			This attribute determines the contents of the sender ID TLV included in CFM messages transmitted
+//			by MPs when no more specific match is found. This attribute is identical to that defined in the
+//			description of the dot1ag MD ME (i.e., excluding code point 5, defer). (R,-W) (mandatory)
+//			(1-byte)
 //
 //		Default Md Level Table
+//			Each entry is a vector of fields, indexed by primary VLAN ID.
+//
+//			Primary VLAN ID (2-bytes)
+//
+//			Table control: This field controls the meaning of a set operation. The 1-byte size of this field
+//			is included in get/get-next operations, but its value is undefined under get-next and should be
+//			ignored by the OLT. (1-byte)
+//
+//			1	Add record to table; overwrite existing record, if any.
+//
+//			2	Delete record from table.
+//
+//			3	Clear all entries from table. This action may affect service and should be used judiciously.
+//
+//			Other values are reserved.
+//
+//			Status: This Boolean field indicates whether this table entry is in effect (true) or whether
+//			(false) it has been overridden by the existence of an MA for the same VID and MD level as this
+//			table's entry, and on which an up MEP is defined. This attribute is read-only. Space should be
+//			allocated for it during set operations, but the value is not used. (1-byte)
+//
+//			Level: This field ranges from 0..7 and specifies the MD level of MHFs under the control of this
+//			instance of the dot1ag default MD level. The additional value 0xFF instructs the bridge to use
+//			the value in the catch-all level attribute. (1-byte)
+//
+//			MHF creation: This attribute determines whether the bridge creates an MHF or not, under
+//			circumstances defined in clause 22.2.3 of [IEEE 802.1ag]. This attribute is an enumeration with
+//			the following values. (1-byte)
+//
+//			1	None. No MHFs are created on this bridge for this MA.
+//
+//			2	Default. The bridge can create MHFs on this VID on any port through which the VID can pass.
+//
+//			3	Explicit. The bridge can create MHFs on this VID on any port through which the VID can pass,
+//			but only if an MEP exists at some lower maintenance level.
+//
+//			4	Defer. This value causes the ONU to use the setting of the catch-all MHF creation attribute.
+//			This is recommended to be the default value.
+//
+//			Sender ID permission: This attribute determines the contents of the sender ID TLV included in
+//			CFM messages transmitted by MPs controlled by this MA. (1-byte)
+//
+//			1	None: the sender ID TLV is not to be sent, default.
+//
+//			2	Chassis: the chassis ID length, chassis ID subtype, and chassis ID fields of the sender ID TLV
+//			are to be sent, but not the management address fields.
+//
+//			3	Manage: the management address fields of the sender ID TLV are to be sent, but the chassis ID
+//			length is to be transmitted with a 0 value, and the chassis ID subtype, and chassis ID fields
+//			are not to be sent.
+//
+//			4	ChassisManage: all chassis ID and management address fields are to be sent.
+//
+//			5	Defer: the contents of the sender ID TLV is determined by the catch-all sender ID permission
+//			attribute.
+//
+//			Associated VLANs list: This field comprises a list of up to 11 additional VLAN IDs associated
+//			with the primary VLAN, 2-bytes each. Unused placeholders, possibly including the entire field,
+//			are set to 0. (22-bytes)
+//
 //			(R,-W) (mandatory) (29-bytes * N entries)
 //
 type Dot1AgDefaultMdLevel struct {
diff --git a/generated/dot1agmaintenanceassociation.go b/generated/dot1agmaintenanceassociation.go
index acb599f..b898665 100644
--- a/generated/dot1agmaintenanceassociation.go
+++ b/generated/dot1agmaintenanceassociation.go
@@ -27,11 +27,11 @@
 
 // Dot1AgMaintenanceAssociationClassID is the 16-bit ID for the OMCI
 // Managed entity Dot1ag maintenance association
-const Dot1AgMaintenanceAssociationClassID ClassID = ClassID(300)
+const Dot1AgMaintenanceAssociationClassID = ClassID(300) // 0x012c
 
 var dot1agmaintenanceassociationBME *ManagedEntityDefinition
 
-// Dot1AgMaintenanceAssociation (class ID #300)
+// Dot1AgMaintenanceAssociation (Class ID: #300 / 0x012c)
 //	This ME models an [IEEE 802.1ag] service defined on a bridge port. An MA is a set of endpoints
 //	on opposite sides of a network, all existing at a defined maintenance level. One of the
 //	endpoints resides on the local ONU; the others are understood to be configured in a consistent
diff --git a/generated/dot1agmaintenancedomain.go b/generated/dot1agmaintenancedomain.go
index aefb298..5f191a5 100644
--- a/generated/dot1agmaintenancedomain.go
+++ b/generated/dot1agmaintenancedomain.go
@@ -27,11 +27,11 @@
 
 // Dot1AgMaintenanceDomainClassID is the 16-bit ID for the OMCI
 // Managed entity Dot1ag maintenance domain
-const Dot1AgMaintenanceDomainClassID ClassID = ClassID(299)
+const Dot1AgMaintenanceDomainClassID = ClassID(299) // 0x012b
 
 var dot1agmaintenancedomainBME *ManagedEntityDefinition
 
-// Dot1AgMaintenanceDomain (class ID #299)
+// Dot1AgMaintenanceDomain (Class ID: #299 / 0x012b)
 //	In [IEEE 802.1ag], a maintenance domain (MD) is a context within which configuration fault
 //	management (CFM) connectivity verification can occur. Individual services (maintenance
 //	associations, MAs) exist within an MD. An MD is created and deleted by the OLT. The MD ME is
diff --git a/generated/dot1agmep.go b/generated/dot1agmep.go
index 8d6db66..44cce8c 100644
--- a/generated/dot1agmep.go
+++ b/generated/dot1agmep.go
@@ -27,11 +27,11 @@
 
 // Dot1AgMepClassID is the 16-bit ID for the OMCI
 // Managed entity Dot1ag MEP
-const Dot1AgMepClassID ClassID = ClassID(302)
+const Dot1AgMepClassID = ClassID(302) // 0x012e
 
 var dot1agmepBME *ManagedEntityDefinition
 
-// Dot1AgMep (class ID #302)
+// Dot1AgMep (Class ID: #302 / 0x012e)
 //	This ME models an MEP as defined primarily in [IEEE 802.1ag] and secondarily in [ITUT Y.1731].
 //	It is created and deleted by the OLT. An MEP exists at one of eight possible maintenance levels,
 //	and resides at the boundary of a MD. It inherits a name, and optionally a set of associated
@@ -43,78 +43,98 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Layer 2 Entity Pointer
-//			Layer 2 entity pointer: Depending on the value of the layer 2 type attribute, this pointer
-//			specifies the MAC bridge port configuration data ME or the IEEE 802.1p mapper service profile ME
-//			with which this MEP is associated. (R,-W, setbycreate) (mandatory) (2-bytes)
-//
-//		Layer 2 Type
-//			Layer 2 type:	This attribute specifies whether the MA is associated with a MAC bridge port
-//			(value 0) or an IEEE 802.1p mapper (value 1). (R,-W, setbycreate) (mandatory) (1-byte)
-//
-//		Ma Pointer
-//			MA pointer:	This pointer specifies the maintenance association with which this MEP is
+//			Depending on the value of the layer 2 type attribute, this pointer specifies the MAC bridge port
+//			configuration data ME or the IEEE 802.1p mapper service profile ME with which this MEP is
 //			associated. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
+//		Layer 2 Type
+//			This attribute specifies whether the MA is associated with a MAC bridge port (value 0) or an
+//			IEEE 802.1p mapper (value 1). (R,-W, setbycreate) (mandatory) (1-byte)
+//
+//		Ma Pointer
+//			This pointer specifies the maintenance association with which this MEP is associated. (R,-W,
+//			setbycreate) (mandatory) (2-bytes)
+//
 //		Mep Id
-//			MEP ID:	This attribute specifies the MEP's own identity in the MA. For a given MA, the MEP ID
-//			must be unique throughout the network defined by the MD. The MEP ID is defined in the range
-//			1..8191. The value 0 indicates that no MEP ID is (yet) configured. (R,-W, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute specifies the MEP's own identity in the MA. For a given MA, the MEP ID must be
+//			unique throughout the network defined by the MD. The MEP ID is defined in the range 1..8191. The
+//			value 0 indicates that no MEP ID is (yet) configured. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Mep Control
+//			This attribute specifies some of the overall behavioural aspects of the MEP. It is interpreted
+//			as follows.
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Primary Vlan
-//			Primary VLAN: This attribute is a 12-bit VLAN ID. The value 0 indicates that the MEP inherits
-//			its primary VLAN from its parent MA. CFM messages, except forwarded LTMs, are tagged with the
-//			primary VLAN ID. If explicitly specified, the value of this attribute must be one of the VLANs
-//			associated with the parent MA. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute is a 12-bit VLAN ID. The value 0 indicates that the MEP inherits its primary VLAN
+//			from its parent MA. CFM messages, except forwarded LTMs, are tagged with the primary VLAN ID. If
+//			explicitly specified, the value of this attribute must be one of the VLANs associated with the
+//			parent MA. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Administrative State
-//			Administrative state: This attribute locks (1) and unlocks (0) the functions performed by this
-//			ME. Administrative state is further described in clause A.1.6. (R,-W, setbycreate) (mandatory)
-//			(1-byte)
+//			This attribute locks (1) and unlocks (0) the functions performed by this ME. Administrative
+//			state is further described in clause A.1.6. (R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Ccm And Ltm Priority
-//			CCM and LTM priority: Ranging from 0..7, this attribute permits CCM and LTM frames to be
-//			explicitly prioritized, which may be needed if flows are separated, e.g., by 802.1p priority.
-//			The priority specified in this attribute is also used in linktrace reply (LTR) frames originated
-//			by this MEP. The value 0xFF selects the IEEE 802.1ag default, whereby CCM and LTM frames are
-//			transmitted with the highest Ethernet priority available. (R,-W, setbycreate) (mandatory)
-//			(1-byte)
+//			Ranging from 0..7, this attribute permits CCM and LTM frames to be explicitly prioritized, which
+//			may be needed if flows are separated, e.g., by 802.1p priority. The priority specified in this
+//			attribute is also used in linktrace reply (LTR) frames originated by this MEP. The value 0xFF
+//			selects the IEEE 802.1ag default, whereby CCM and LTM frames are transmitted with the highest
+//			Ethernet priority available. (R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Egress Identifier
-//			Egress identifier: This attribute comprises 8-bytes to be included in LTMs. They allow received
-//			LTRs to be directed to the correct originator. The attribute includes the originator MAC address
-//			and a locally defined identifier. If this field is 0, the ONU uses the MEP's MAC address, with 0
-//			as the locally defined identifier. (R,-W, setbycreate) (mandatory) (8-bytes)
+//			This attribute comprises 8-bytes to be included in LTMs. They allow received LTRs to be directed
+//			to the correct originator. The attribute includes the originator MAC address and a locally
+//			defined identifier. If this field is 0, the ONU uses the MEP's MAC address, with 0 as the
+//			locally defined identifier. (R,-W, setbycreate) (mandatory) (8-bytes)
 //
 //		Peer Mep Ids
-//			Peer MEP IDs: This attribute lists the expected peer MEPs for CCMs, 2-bytes per MEP ID. [IEEE
-//			802.1ag] allows for multipoint networks, and therefore a list of peer MEPs. This attribute
-//			allows for up to 12 peers for a given MEP, though GPON applications are expected to need only a
-//			single peer. Missing or unexpected messages trigger alarm declaration after a soak interval.
-//			Unused peer MEP slots should be set to 0. (R,-W) (mandatory) (24-bytes)
+//			This attribute lists the expected peer MEPs for CCMs, 2-bytes per MEP ID. [IEEE 802.1ag] allows
+//			for multipoint networks, and therefore a list of peer MEPs. This attribute allows for up to 12
+//			peers for a given MEP, though GPON applications are expected to need only a single peer. Missing
+//			or unexpected messages trigger alarm declaration after a soak interval. Unused peer MEP slots
+//			should be set to 0. (R,-W) (mandatory) (24-bytes)
 //
 //		Eth Ais Control
+//			This attribute controls the generation of Ethernet alarm indication signal (AIS) frames when
+//			they are enabled through the MEP control attribute. It is interpreted as follows:
+//
 //			(R,-W, setbycreate) (mandatory if ETH AIS is enabled) (1-byte)
 //
 //		Fault Alarm Threshold
+//			This attribute specifies the lowest priority alarm that is allowed to generate a fault alarm.
+//			The value 0 specifies that the ONU uses its internal default. It is defined as follows.
+//
+//			1	All defects generate alarms after suitable soaking, including AIS and RDICCM.
+//
+//			2	Alarm generated only by one of: MACstatus, RemoteCCM, ErrorCCM, XconCCM. This value is
+//			recommended as the default in [IEEE 802.1ag].
+//
+//			3	Alarm generated only by one of: RemoteCCM, ErrorCCM, XconCCM.
+//
+//			4	Alarm generated only by one of: ErrorCCM, XconCCM.
+//
+//			5	Alarm generated only by: XconCCM.
+//
+//			6	No alarms are to be reported. This setting may be useful during configuration of services
+//			across the network when spurious alarms could otherwise be generated.
+//
 //			(R,-W, setbycreate) (optional) (1-byte)
 //
 //		Alarm Declaration Soak Time
-//			Alarm declaration soak time: This attribute defines the defect soak time that must elapse before
-//			the MEP declares an alarm. It is expressed in 10-ms units with a range of 250 to 1000, i.e.,
-//			2.5-s to 10-s. The default is recommended to be 2.5 seconds. (R,-W) (mandatory) (2-bytes)
+//			This attribute defines the defect soak time that must elapse before the MEP declares an alarm.
+//			It is expressed in 10-ms units with a range of 250 to 1000, i.e., 2.5-s to 10-s. The default is
+//			recommended to be 2.5 seconds. (R,-W) (mandatory) (2-bytes)
 //
 //		Alarm Clear Soak Time
-//			Alarm clear soak time: This attribute defines the defect-free soak time that must elapse before
-//			the MEP clears an alarm. It is expressed in intervals of 10-ms with a range of 250 to 1-000,
-//			i.e., 2.5-s to 10-s. The default is recommended to be 10-s. (R,-W) (mandatory) (2-bytes)
+//			This attribute defines the defect-free soak time that must elapse before the MEP clears an
+//			alarm. It is expressed in intervals of 10-ms with a range of 250 to 1-000, i.e., 2.5-s to 10-s.
+//			The default is recommended to be 10-s. (R,-W) (mandatory) (2-bytes)
 //
 type Dot1AgMep struct {
 	ManagedEntityDefinition
diff --git a/generated/dot1ratelimiter.go b/generated/dot1ratelimiter.go
index 107a024..71c88c5 100644
--- a/generated/dot1ratelimiter.go
+++ b/generated/dot1ratelimiter.go
@@ -27,11 +27,11 @@
 
 // Dot1RateLimiterClassID is the 16-bit ID for the OMCI
 // Managed entity Dot1 rate limiter
-const Dot1RateLimiterClassID ClassID = ClassID(298)
+const Dot1RateLimiterClassID = ClassID(298) // 0x012a
 
 var dot1ratelimiterBME *ManagedEntityDefinition
 
-// Dot1RateLimiter (class ID #298)
+// Dot1RateLimiter (Class ID: #298 / 0x012a)
 //	This ME allows rate limits to be defined for various types of upstream traffic that are
 //	processed by IEEE 802.1 bridges or related structures.
 //
@@ -41,31 +41,37 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Parent Me Pointer
-//			Parent ME pointer: This attribute points to an instance of a ME. The type of ME is determined by
-//			the TP type attribute. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute points to an instance of a ME. The type of ME is determined by the TP type
+//			attribute. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Tp Type
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
-//		Upstream Unicast Flood Rate Pointer
-//			Upstream unicast flood rate pointer: This attribute points to an instance of the traffic
-//			descriptor that governs the rate of upstream unicast packets whose DA is unknown to the bridge.
-//			A null pointer specifies that no administrative limit is to be imposed. (R,-W, setbycreate)
-//			(optional) (2-bytes)
+//			This attribute identifies the type of TP associated with this dot1 rate limiter. Valid values
+//			are:
 //
-//		Upstream Broadcast Rate Pointer
-//			Upstream broadcast rate pointer: This attribute points to an instance of the traffic descriptor
-//			that governs the rate of upstream broadcast packets. A null pointer specifies that no
+//			1	MAC bridge service profile
+//
+//			2	IEEE 802.1p mapper service profile
+//
+//		Upstream Unicast Flood Rate Pointer
+//			This attribute points to an instance of the traffic descriptor that governs the rate of upstream
+//			unicast packets whose DA is unknown to the bridge. A null pointer specifies that no
 //			administrative limit is to be imposed. (R,-W, setbycreate) (optional) (2-bytes)
 //
+//		Upstream Broadcast Rate Pointer
+//			This attribute points to an instance of the traffic descriptor that governs the rate of upstream
+//			broadcast packets. A null pointer specifies that no administrative limit is to be imposed.
+//			(R,-W, setbycreate) (optional) (2-bytes)
+//
 //		Upstream Multicast Payload Rate Pointer
-//			Upstream multicast payload rate pointer: This attribute points to an instance of the traffic
-//			descriptor that governs the rate of upstream multicast payload packets. A null pointer specifies
-//			that no administrative limit is to be imposed. (R,-W, setbycreate) (optional) (2-bytes)
+//			This attribute points to an instance of the traffic descriptor that governs the rate of upstream
+//			multicast payload packets. A null pointer specifies that no administrative limit is to be
+//			imposed. (R,-W, setbycreate) (optional) (2-bytes)
 //
 type Dot1RateLimiter struct {
 	ManagedEntityDefinition
diff --git a/generated/dot1xconfigurationprofile.go b/generated/dot1xconfigurationprofile.go
index 57abc1d..ad53d44 100644
--- a/generated/dot1xconfigurationprofile.go
+++ b/generated/dot1xconfigurationprofile.go
@@ -27,11 +27,11 @@
 
 // Dot1XConfigurationProfileClassID is the 16-bit ID for the OMCI
 // Managed entity Dot1X configuration profile
-const Dot1XConfigurationProfileClassID ClassID = ClassID(291)
+const Dot1XConfigurationProfileClassID = ClassID(291) // 0x0123
 
 var dot1xconfigurationprofileBME *ManagedEntityDefinition
 
-// Dot1XConfigurationProfile (class ID #291)
+// Dot1XConfigurationProfile (Class ID: #291 / 0x0123)
 //	An instance of this ME represents a set of attributes that control an ONU's 802.1X operation
 //	with regard to IEEE 802 services. An instance of this ME is created by the ONU if it is capable
 //	of supporting [IEEE 802.1X] authentication of CPE.
@@ -41,48 +41,68 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute provides a unique number for each instance of this ME. There
-//			is at most one instance, number 0. (R) (mandatory) (2-bytes)
+//			This attribute provides a unique number for each instance of this ME. There is at most one
+//			instance, number 0. (R) (mandatory) (2-bytes)
 //
 //		Circuit Id Prefix
-//			Circuit ID prefix: This attribute is a pointer to a large string ME whose content appears as the
-//			prefix of the NAS port ID in radius access-request messages. The remainder of the NAS port ID
-//			field is local information (for example, slot-port, appended by the ONU itself). The default
-//			value of this attribute is the null pointer 0. (R,-W) (mandatory) (2-bytes)
+//			This attribute is a pointer to a large string ME whose content appears as the prefix of the NAS
+//			port ID in radius access-request messages. The remainder of the NAS port ID field is local
+//			information (for example, slot-port, appended by the ONU itself). The default value of this
+//			attribute is the null pointer 0. (R,-W) (mandatory) (2-bytes)
 //
 //		Fallback Policy
-//			Fallback policy: When set to 1 (deny), this attribute causes IEEE-802.1X conversations to fail
-//			when no external authentication server is accessible, such that no Ethernet service is provided.
-//			The default value 0 causes IEEE-802.1X conversations to succeed when no external authentication
-//			server is accessible. (R,-W) (mandatory) (1-byte)
+//			When set to 1 (deny), this attribute causes IEEE-802.1X conversations to fail when no external
+//			authentication server is accessible, such that no Ethernet service is provided. The default
+//			value 0 causes IEEE-802.1X conversations to succeed when no external authentication server is
+//			accessible. (R,-W) (mandatory) (1-byte)
 //
 //		Auth Server 1
-//			Auth server 1: This attribute is a pointer to a large string ME that contains the URI of the
-//			first choice radius authentication server. The value 0 indicates that no radius authentication
-//			server is specified. (R,-W) (mandatory) (2-bytes)
+//			This attribute is a pointer to a large string ME that contains the URI of the first choice
+//			radius authentication server. The value 0 indicates that no radius authentication server is
+//			specified. (R,-W) (mandatory) (2-bytes)
 //
 //		Shared Secret Auth1
-//			Shared secret auth1: This attribute is the shared secret for the first radius authentication
-//			server. It is a null-terminated character string. (R,-W) (mandatory) (25-bytes)
+//			This attribute is the shared secret for the first radius authentication server. It is a null-
+//			terminated character string. (R,-W) (mandatory) (25-bytes)
+//
+//			The following two pairs of attributes are defined in the same way:
 //
 //		Auth Server 2
-//			Auth server 2:	(R,-W) (optional) (2-bytes)
+//			(R,-W) (optional) (2-bytes)
 //
 //		Shared Secret Auth2
-//			Shared secret auth2:	(R,-W) (optional) (25-bytes)
+//			(R,-W) (optional) (25-bytes)
 //
 //		Auth Server 3
-//			Auth server 3:	(R,-W) (optional) (2-bytes)
+//			(R,-W) (optional) (2-bytes)
 //
 //		Shared Secret Auth3
-//			Shared secret auth3:	(R,-W) (optional) (25-bytes)
+//			(R,-W) (optional) (25-bytes)
 //
 //		Olt Proxy Address
-//			OLT proxy address: This attribute indicates the IP address of a possible proxy at the OLT for
-//			IEEE-802.1X radius messages. The default value 0.0.0.0 indicates that no proxy is required.
-//			(R,-W) (optional) (4-bytes)
+//			This attribute indicates the IP address of a possible proxy at the OLT for IEEE-802.1X radius
+//			messages. The default value 0.0.0.0 indicates that no proxy is required. (R,-W) (optional)
+//			(4-bytes)
 //
 //		Calling Station Id Format
+//			Radius messages initiated by the ONU contain a calling-station-ID field that is specified to be
+//			the supplicant's MAC address in upper-case ASCII form, with bytes separated by a delimiter. This
+//			attribute permits specification of the delimiter. (R,-W) (optional) (2-bytes)
+//
+//			Value	Meaning
+//
+//			0	ONU's internal default
+//
+//			1	Hyphen (-) delimiter
+//
+//			2	Colon (:) delimiter
+//
+//			3	No delimiter
+//
+//			0x20 - 0x7E	Use this value as the delimiter
+//
+//			0xF0 - 0xFE	Vendor-specific use
+//
 //			Other values are reserved.
 //
 type Dot1XConfigurationProfile struct {
diff --git a/generated/dot1xperformancemonitoringhistorydata.go b/generated/dot1xperformancemonitoringhistorydata.go
index 9cf56c3..e9d2177 100644
--- a/generated/dot1xperformancemonitoringhistorydata.go
+++ b/generated/dot1xperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // Dot1XPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity Dot1X performance monitoring history data
-const Dot1XPerformanceMonitoringHistoryDataClassID ClassID = ClassID(292)
+const Dot1XPerformanceMonitoringHistoryDataClassID = ClassID(292) // 0x0124
 
 var dot1xperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// Dot1XPerformanceMonitoringHistoryData (class ID #292)
+// Dot1XPerformanceMonitoringHistoryData (Class ID: #292 / 0x0124)
 //	This ME collects performance statistics on an ONU's IEEE 802.1X CPE authentication operation.
 //	Instances of this ME are created and deleted by the OLT.
 //
@@ -43,68 +43,59 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of a PPTP. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of a PPTP. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 and 2 MEs
 //			that contains PM threshold values. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Eapol Frames Received
-//			EAPOL frames received: This attribute counts received valid EAPOL frames of any type. (R)
-//			(mandatory) (4-bytes)
+//			This attribute counts received valid EAPOL frames of any type. (R) (mandatory) (4-bytes)
 //
 //		Eapol Frames Transmitted
-//			EAPOL frames transmitted: This attribute counts transmitted EAPOL frames of any type. (R)
-//			(mandatory) (4-bytes)
+//			This attribute counts transmitted EAPOL frames of any type. (R) (mandatory) (4-bytes)
 //
 //		Eapol Start Frames Received
-//			EAPOL start frames received: This attribute counts received EAPOL start frames. (R) (mandatory)
-//			(4-bytes)
+//			This attribute counts received EAPOL start frames. (R) (mandatory) (4-bytes)
 //
 //		Eapol Logoff Frames Received
-//			EAPOL logoff frames received: This attribute counts received EAPOL logoff frames. (R)
-//			(mandatory) (4-bytes)
+//			This attribute counts received EAPOL logoff frames. (R) (mandatory) (4-bytes)
 //
 //		Invalid Eapol Frames Received
-//			Invalid EAPOL frames received: This attribute counts received EAPOL frames in which the frame
-//			type was not recognized. (R) (mandatory) (4-bytes)
+//			This attribute counts received EAPOL frames in which the frame type was not recognized. (R)
+//			(mandatory) (4-bytes)
 //
 //		Eap Resp_Id Frames Received
 //			EAP resp/id frames received: This attribute counts received EAP response frames containing an
 //			identifier type field. (R) (mandatory) (4-bytes)
 //
 //		Eap Response Frames Received
-//			EAP response frames received: This attribute counts received EAP response frames, other than
-//			resp/id frames. (R) (mandatory) (4-bytes)
+//			This attribute counts received EAP response frames, other than resp/id frames. (R) (mandatory)
+//			(4-bytes)
 //
 //		Eap Initial Request Frames Transmitted
-//			EAP initial request frames transmitted: This attribute counts transmitted request frames
-//			containing an identifier type field. In [IEEE 802.1X], this is also called ReqId. (R)
-//			(mandatory) (4-bytes)
+//			This attribute counts transmitted request frames containing an identifier type field. In [IEEE
+//			802.1X], this is also called ReqId. (R) (mandatory) (4-bytes)
 //
 //		Eap Request Frames Transmitted
-//			EAP request frames transmitted: This attribute counts transmitted request frames, other than
-//			request/id frames. (R) (mandatory) (4-bytes)
+//			This attribute counts transmitted request frames, other than request/id frames. (R) (mandatory)
+//			(4-bytes)
 //
 //		Eap Length Error Frames Received
-//			EAP length error frames received: This attribute counts received EAPOL frames whose packet body
-//			length field was invalid. (R) (mandatory) (4-bytes)
+//			This attribute counts received EAPOL frames whose packet body length field was invalid. (R)
+//			(mandatory) (4-bytes)
 //
 //		Eap Success Frames Generated Autonomously
-//			EAP success frames generated autonomously: This attribute counts EAPOL success frames generated
-//			according to the local fallback policy because no radius server was available. (R) (mandatory)
-//			(4-bytes)
+//			This attribute counts EAPOL success frames generated according to the local fallback policy
+//			because no radius server was available. (R) (mandatory) (4-bytes)
 //
 //		Eap Failure Frames Generated Autonomously
-//			EAP failure frames generated autonomously: This attribute counts EAPOL failure frames generated
-//			according to the local fallback policy because no radius server was available. (R) (mandatory)
-//			(4-bytes)
+//			This attribute counts EAPOL failure frames generated according to the local fallback policy
+//			because no radius server was available. (R) (mandatory) (4-bytes)
 //
 type Dot1XPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/dot1xportextensionpackage.go b/generated/dot1xportextensionpackage.go
index 428d9de..8970c4a 100644
--- a/generated/dot1xportextensionpackage.go
+++ b/generated/dot1xportextensionpackage.go
@@ -27,11 +27,11 @@
 
 // Dot1XPortExtensionPackageClassID is the 16-bit ID for the OMCI
 // Managed entity Dot1X port extension package
-const Dot1XPortExtensionPackageClassID ClassID = ClassID(290)
+const Dot1XPortExtensionPackageClassID = ClassID(290) // 0x0122
 
 var dot1xportextensionpackageBME *ManagedEntityDefinition
 
-// Dot1XPortExtensionPackage (class ID #290)
+// Dot1XPortExtensionPackage (Class ID: #290 / 0x0122)
 //	An instance of this ME represents a set of attributes that control a port's IEEE 802.1X
 //	operation. It is created and deleted autonomously by the ONU upon the creation or deletion of a
 //	PPTP that supports [IEEE 802.1X] authentication of customer premises equipment (CPE).
@@ -42,54 +42,110 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute provides a unique number for each instance of this ME. Its
-//			value is the same as that of its associated PPTP (i.e., slot and port number). (R) (mandatory)
-//			(2-bytes)
+//			This attribute provides a unique number for each instance of this ME. Its value is the same as
+//			that of its associated PPTP (i.e., slot and port number). (R) (mandatory) (2-bytes)
 //
 //		Dot1X Enable
-//			Dot1x enable: If true, this Boolean attribute forces the associated port to authenticate via
-//			[IEEE 802.1X] as a precondition of normal service. The default value false does not impose IEEE
-//			802.1X authentication on the associated port. (R,-W) (mandatory) (1-byte)
+//			If true, this Boolean attribute forces the associated port to authenticate via [IEEE 802.1X] as
+//			a precondition of normal service. The default value false does not impose IEEE 802.1X
+//			authentication on the associated port. (R,-W) (mandatory) (1-byte)
 //
 //		Action Register
+//			This attribute defines a set of actions that can be performed on the associated port. The act of
+//			writing to the register causes the specified action.
+//
+//			1	Force re-authentication - this opcode initiates an IEEE-802.1X reauthentication conversation
+//			with the associated port. The port remains in its current authorization state until the
+//			conversation concludes.
+//
+//			2	Force unauthenticated - this opcode initiates an IEEE-802.1X authentication conversation whose
+//			outcome is predestined to fail, thereby disabling normal Ethernet service on the port. The
+//			port's provisioning is not changed, such that upon re-initialization, a new IEEE-802.1X
+//			conversation may restore service without prejudice.
+//
+//			3	Force authenticated - this opcode initiates an IEEE-802.1X authentication conversation whose
+//			outcome is predestined to succeed, thereby unconditionally enabling normal Ethernet service on
+//			the port. The port's provisioning is not changed, such that upon re-initialization, a new
+//			IEEE-802.1X conversation is required.
+//
 //			(W) (mandatory) (1-byte)
 //
 //		Authenticator Pae State
+//			4	Authenticated
+//
+//			5	Aborting
+//
+//			6	Held
+//
+//			7	Force auth
+//
+//			8	Force unauth
+//
+//			9	Restart
+//
 //			(R) (optional) (1-byte)
 //
+//			This attribute returns the value of the port's PAE state. States are further described in [IEEE
+//			802.1X]. Values are coded as follows.
+//
+//			0	Initialize
+//
+//			1	Disconnected
+//
+//			2	Connecting
+//
+//			3	Authenticating
+//
 //		Backend Authentication State
+//			This attribute returns the value of the port's back-end authentication state. States are further
+//			described in [IEEE 802.1X]. Values are coded as follows.
+//
+//			0	Request
+//
+//			1	Response
+//
+//			2	Success
+//
+//			3	Fail
+//
+//			4	Timeout
+//
+//			5	Idle
+//
+//			6	Initialize
+//
+//			7	Ignore
+//
 //			(R) (optional) (1-byte)
 //
 //		Admin Controlled Directions
-//			Admin controlled directions: This attribute controls the directionality of the port's
-//			authentication requirement. The default value 0 indicates that control is imposed in both
-//			directions. The value 1 indicates that control is imposed only on traffic from the subscriber
-//			towards the network. (R,-W) (optional) (1-byte)
+//			This attribute controls the directionality of the port's authentication requirement. The default
+//			value 0 indicates that control is imposed in both directions. The value 1 indicates that control
+//			is imposed only on traffic from the subscriber towards the network. (R,-W) (optional) (1-byte)
 //
 //		Operational Controlled Directions
-//			Operational controlled directions: This attribute indicates the directionality of the port's
-//			current authentication state. The value 0 indicates that control is imposed in both directions.
-//			The value 1 indicates that control is imposed only on traffic from the subscriber towards the
-//			network. (R) (optional) (1-byte)
+//			This attribute indicates the directionality of the port's current authentication state. The
+//			value 0 indicates that control is imposed in both directions. The value 1 indicates that control
+//			is imposed only on traffic from the subscriber towards the network. (R) (optional) (1-byte)
 //
 //		Authenticator Controlled Port Status
-//			Authenticator controlled port status: This attribute indicates whether the controlled port is
-//			currently authorized (1) or unauthorized (2). (R) (optional) (1-byte)
+//			This attribute indicates whether the controlled port is currently authorized (1) or unauthorized
+//			(2). (R) (optional) (1-byte)
 //
 //		Quiet Period
-//			Quiet period: This attribute specifies the interval between EAP request/identity invitations
-//			sent to the peer. Other events such as carrier present or EAPOL start frames from the peer may
-//			trigger an EAP request/identity frame from the ONU at any time; this attribute controls the
-//			ONU's periodic behaviour in the absence of these other inputs. It is expressed in seconds.
-//			(R,-W) (optional) (2-bytes)
+//			This attribute specifies the interval between EAP request/identity invitations sent to the peer.
+//			Other events such as carrier present or EAPOL start frames from the peer may trigger an EAP
+//			request/identity frame from the ONU at any time; this attribute controls the ONU's periodic
+//			behaviour in the absence of these other inputs. It is expressed in seconds. (R,-W) (optional)
+//			(2-bytes)
 //
 //		Server Timeout Period
-//			Server timeout period: This attribute specifies the time the ONU will wait for a response from
-//			the radius server before timing out. Within this maximum interval, the ONU may initiate several
-//			retransmissions with exponentially increasing delay. Upon timeout, the ONU may try another
-//			radius server if there is one, or invoke the fallback policy, if no alternate radius servers are
-//			available. Server timeout is expressed in seconds, with a default value of 30 and a maximum
-//			value of 65535. (R,-W) (optional) (2-bytes)
+//			This attribute specifies the time the ONU will wait for a response from the radius server before
+//			timing out. Within this maximum interval, the ONU may initiate several retransmissions with
+//			exponentially increasing delay. Upon timeout, the ONU may try another radius server if there is
+//			one, or invoke the fallback policy, if no alternate radius servers are available. Server timeout
+//			is expressed in seconds, with a default value of 30 and a maximum value of 65535. (R,-W)
+//			(optional) (2-bytes)
 //
 //		Re_Authentication Period
 //			Re-authentication period: This attribute records the re-authentication interval specified by the
@@ -102,9 +158,9 @@
 //			only meaningful after a port has been authenticated. (R) (optional) (1-byte)
 //
 //		Key Transmission Enabled
-//			Key transmission enabled: This Boolean attribute indicates whether key transmission is enabled
-//			(true) or not (false). This feature is not required; the parameter is listed here for
-//			completeness vis-`a-vis [IEEE 802.1X]. (R,-W) (optional) (1-byte)
+//			This Boolean attribute indicates whether key transmission is enabled (true) or not (false). This
+//			feature is not required; the parameter is listed here for completeness vis-`a-vis [IEEE 802.1X].
+//			(R,-W) (optional) (1-byte)
 //
 type Dot1XPortExtensionPackage struct {
 	ManagedEntityDefinition
diff --git a/generated/efmbondinggroup.go b/generated/efmbondinggroup.go
index 299f00d..b569180 100644
--- a/generated/efmbondinggroup.go
+++ b/generated/efmbondinggroup.go
@@ -27,11 +27,11 @@
 
 // EfmBondingGroupClassID is the 16-bit ID for the OMCI
 // Managed entity EFM bonding group
-const EfmBondingGroupClassID ClassID = ClassID(418)
+const EfmBondingGroupClassID = ClassID(418) // 0x01a2
 
 var efmbondinggroupBME *ManagedEntityDefinition
 
-// EfmBondingGroup (class ID #418)
+// EfmBondingGroup (Class ID: #418 / 0x01a2)
 //	The EFM bonding group represents a group of links that are bonded. In [IEEE 802.3], a bonding
 //	group is known as a PAF [physical medium entity (PME) aggregation function] and a link is known
 //	as a PME instance of this ME are created and deleted by the OLT.
@@ -41,28 +41,44 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The value 0 is
-//			reserved. (R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. The value 0 is reserved. (R,
+//			setbycreate) (mandatory) (2-bytes)
 //
 //		Group Id
-//			Group ID: This attribute is the unique number representing this bonding group. See clause
-//			C.3.1.1 of [ITU-T G.998.2]. (R,-W, setbycreate) (mandatory) (6-bytes)
+//			This attribute is the unique number representing this bonding group. See clause C.3.1.1 of
+//			[ITU-T G.998.2]. (R,-W, setbycreate) (mandatory) (6-bytes)
 //
 //		Minimum Upstream Group Rate
-//			Minimum upstream group rate: This attribute sets the minimum upstream group rate, in bits per
-//			second, for this EFM Group. This attribute is used to determine the group US rate low alarm
-//			status. The group US rate low alarm means that the aggregate upstream rate of all active links
-//			associated with this group is less than the minimum upstream group rate. The default value for
-//			this rate is zero. (R,-W) (mandatory, setbycreate) (4-bytes)
+//			This attribute sets the minimum upstream group rate, in bits per second, for this EFM Group.
+//			This attribute is used to determine the group US rate low alarm status. The group US rate low
+//			alarm means that the aggregate upstream rate of all active links associated with this group is
+//			less than the minimum upstream group rate. The default value for this rate is zero. (R,-W)
+//			(mandatory, setbycreate) (4-bytes)
 //
 //		Minimum Downstream Group Rate
-//			Minimum downstream group rate: This attribute sets the minimum downstream group rate, in bits
-//			per second, for this EFM Group. This attribute is used to determine the group DS rate low alarm
-//			status. The group DS rate low alarm means that the aggregate downstream rate of all active links
-//			associated with this group is less than the minimum downstream group rate. The default value for
-//			this rate is zero. (R,-W) (mandatory) (4-bytes, setbycreate)
+//			This attribute sets the minimum downstream group rate, in bits per second, for this EFM Group.
+//			This attribute is used to determine the group DS rate low alarm status. The group DS rate low
+//			alarm means that the aggregate downstream rate of all active links associated with this group is
+//			less than the minimum downstream group rate. The default value for this rate is zero. (R,-W)
+//			(mandatory) (4-bytes, setbycreate)
 //
 //		Group Alarm Enable
+//			This bit mapped attribute enables the various group alarms. A bit value of 1 means "enable".
+//
+//			Bit	Meaning
+//
+//			1 (LSB)	Group down
+//
+//			2	Group partial
+//
+//			3	Group US rate low
+//
+//			4	Group DS rate low
+//
+//			5	4x rate ratio
+//
+//			6-8	Reserved
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
 type EfmBondingGroup struct {
diff --git a/generated/efmbondinggroupperformancemonitoringhistorydata.go b/generated/efmbondinggroupperformancemonitoringhistorydata.go
index 6157d8f..55a24c3 100644
--- a/generated/efmbondinggroupperformancemonitoringhistorydata.go
+++ b/generated/efmbondinggroupperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // EfmBondingGroupPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity EFM bonding group performance monitoring history data
-const EfmBondingGroupPerformanceMonitoringHistoryDataClassID ClassID = ClassID(420)
+const EfmBondingGroupPerformanceMonitoringHistoryDataClassID = ClassID(420) // 0x01a4
 
 var efmbondinggroupperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// EfmBondingGroupPerformanceMonitoringHistoryData (class ID #420)
+// EfmBondingGroupPerformanceMonitoringHistoryData (Class ID: #420 / 0x01a4)
 //	This ME collects PM data as seen at the xTU-C. Instances of this ME are created and deleted by
 //	the OLT.
 //
@@ -40,51 +40,49 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the EFM bonding group. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the EFM bonding group. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 and 2 MEs
 //			that contain PM threshold values. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Rx Bad Fragments
-//			Rx bad fragments: Clause 45.2.3.33 of [IEEE 802.3]. (R) (mandatory) (4-bytes)
+//			Clause 45.2.3.33 of [IEEE 802.3]. (R) (mandatory) (4-bytes)
 //
 //		Rx Lost Fragments
-//			Rx lost fragments: Clause 45.2.3.34 of [IEEE 802.3]. (R) (mandatory) (4-bytes)
+//			Clause 45.2.3.34 of [IEEE 802.3]. (R) (mandatory) (4-bytes)
 //
 //		Rx Lost Starts
-//			Rx lost starts: Clause 45.2.3.35 of [IEEE 802.3]. (R) (mandatory) (4-bytes)
+//			Clause 45.2.3.35 of [IEEE 802.3]. (R) (mandatory) (4-bytes)
 //
 //		Rx Lost Ends
-//			Rx lost ends: Clause 45.2.3.36 of [IEEE 802.3]. (R) (mandatory) (4-bytes)
+//			Clause 45.2.3.36 of [IEEE 802.3]. (R) (mandatory) (4-bytes)
 //
 //		Rx Frames
-//			Rx frames: Number of Ethernet frames received over this group. (R) (mandatory) (4-bytes)
+//			Number of Ethernet frames received over this group. (R) (mandatory) (4-bytes)
 //
 //		Tx Frames
-//			Tx frames: Number of Ethernet frames transmitted over this group. (R) (mandatory) (4-bytes)
+//			Number of Ethernet frames transmitted over this group. (R) (mandatory) (4-bytes)
 //
 //		Rx Bytes
-//			Rx bytes: Number of bytes contained in the Ethernet frames received over this group. (R)
-//			(mandatory) (8-bytes)
+//			Number of bytes contained in the Ethernet frames received over this group. (R) (mandatory)
+//			(8-bytes)
 //
 //		Tx Bytes
-//			Tx bytes: Number of bytes contained in the Ethernet frames transmitted over this group. (R)
-//			(mandatory) (8-bytes)
+//			Number of bytes contained in the Ethernet frames transmitted over this group. (R) (mandatory)
+//			(8-bytes)
 //
 //		Tx Discarded Frames
-//			Tx discarded frames: Number of Ethernet frames discarded by the group transmit function. (R)
-//			(mandatory) (4-bytes)
+//			Number of Ethernet frames discarded by the group transmit function. (R) (mandatory) (4-bytes)
 //
 //		Tx Discarded Bytes
-//			Tx discarded bytes: Number of bytes contained in the Ethernet frames discarded by the group
-//			transmit function. (R) (mandatory) (4-bytes)
+//			Number of bytes contained in the Ethernet frames discarded by the group transmit function. (R)
+//			(mandatory) (4-bytes)
 //
 type EfmBondingGroupPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/efmbondinggroupperformancemonitoringhistorydatapart2.go b/generated/efmbondinggroupperformancemonitoringhistorydatapart2.go
index e7d9c7e..ed3a34c 100644
--- a/generated/efmbondinggroupperformancemonitoringhistorydatapart2.go
+++ b/generated/efmbondinggroupperformancemonitoringhistorydatapart2.go
@@ -27,11 +27,11 @@
 
 // EfmBondingGroupPerformanceMonitoringHistoryDataPart2ClassID is the 16-bit ID for the OMCI
 // Managed entity EFM bonding group performance monitoring history data part 2
-const EfmBondingGroupPerformanceMonitoringHistoryDataPart2ClassID ClassID = ClassID(421)
+const EfmBondingGroupPerformanceMonitoringHistoryDataPart2ClassID = ClassID(421) // 0x01a5
 
 var efmbondinggroupperformancemonitoringhistorydatapart2BME *ManagedEntityDefinition
 
-// EfmBondingGroupPerformanceMonitoringHistoryDataPart2 (class ID #421)
+// EfmBondingGroupPerformanceMonitoringHistoryDataPart2 (Class ID: #421 / 0x01a5)
 //	This ME collects PM data as seen at the xTU-C. Instances of this ME are created and deleted by
 //	the OLT.
 //
@@ -40,65 +40,58 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the EFM bonding group. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the EFM bonding group. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 and 2 MEs
 //			that contain PM threshold values. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Rx Unicast Frames
-//			Rx unicast frames: Number of unicast Ethernet frames received over this group. (R) (mandatory)
-//			(4-bytes)
+//			Number of unicast Ethernet frames received over this group. (R) (mandatory) (4-bytes)
 //
 //		Tx Unicast Frames
-//			Tx unicast frames: Number of unicast Ethernet frames transmitted over this group. (R)
-//			(mandatory) (4-bytes)
+//			Number of unicast Ethernet frames transmitted over this group. (R) (mandatory) (4-bytes)
 //
 //		Rx Unicast Bytes
-//			Rx unicast bytes: Number of bytes contained in the unicast Ethernet frames received over this
-//			group. (R) (mandatory) (8-bytes)
+//			Number of bytes contained in the unicast Ethernet frames received over this group. (R)
+//			(mandatory) (8-bytes)
 //
 //		Tx Unicast Bytes
-//			Tx unicast bytes: Number of bytes contained in the unicast Ethernet frames transmitted over this
-//			group. (R) (mandatory) (8-bytes)
+//			Number of bytes contained in the unicast Ethernet frames transmitted over this group. (R)
+//			(mandatory) (8-bytes)
 //
 //		Rx Broadcast Frames
-//			Rx broadcast frames: Number of broadcast Ethernet frames received over this group. (R)
-//			(mandatory) (4-bytes)
+//			Number of broadcast Ethernet frames received over this group. (R) (mandatory) (4-bytes)
 //
 //		Tx Broadcast Frames
-//			Tx broadcast frames: Number of broadcast Ethernet frames transmitted over this group. (R)
-//			(mandatory) (4-bytes)
+//			Number of broadcast Ethernet frames transmitted over this group. (R) (mandatory) (4-bytes)
 //
 //		Rx Broadcast Bytes
-//			Rx broadcast bytes: Number of bytes contained in the broadcast Ethernet frames received over
-//			this group. (R) (mandatory) (8-bytes)
+//			Number of bytes contained in the broadcast Ethernet frames received over this group. (R)
+//			(mandatory) (8-bytes)
 //
 //		Tx Broadcast Bytes
-//			Tx broadcast bytes: Number of bytes contained in the broadcast Ethernet frames transmitted over
-//			this group. (R) (mandatory) (8-bytes)
+//			Number of bytes contained in the broadcast Ethernet frames transmitted over this group. (R)
+//			(mandatory) (8-bytes)
 //
 //		Rx Multicast Frames
-//			Rx multicast frames: Number of multicast Ethernet frames received over this group. (R)
-//			(mandatory) (4-bytes)
+//			Number of multicast Ethernet frames received over this group. (R) (mandatory) (4-bytes)
 //
 //		Tx Multicast Frames
-//			Tx multicast frames: Number of multicast Ethernet frames transmitted over this group. (R)
-//			(mandatory) (4-bytes)
+//			Number of multicast Ethernet frames transmitted over this group. (R) (mandatory) (4-bytes)
 //
 //		Rx Multicast Bytes
-//			Rx multicast bytes: Number of bytes contained in the multicast Ethernet frames received over
-//			this group. (R) (mandatory) (8-bytes)
+//			Number of bytes contained in the multicast Ethernet frames received over this group. (R)
+//			(mandatory) (8-bytes)
 //
 //		Tx Multicast Bytes
-//			Tx multicast bytes: Number of bytes contained in the multicast Ethernet frames transmitted over
-//			this group. (R) (mandatory) (8-bytes)
+//			Number of bytes contained in the multicast Ethernet frames transmitted over this group. (R)
+//			(mandatory) (8-bytes)
 //
 type EfmBondingGroupPerformanceMonitoringHistoryDataPart2 struct {
 	ManagedEntityDefinition
diff --git a/generated/efmbondinglink.go b/generated/efmbondinglink.go
index 089195e..4df2d36 100644
--- a/generated/efmbondinglink.go
+++ b/generated/efmbondinglink.go
@@ -27,11 +27,11 @@
 
 // EfmBondingLinkClassID is the 16-bit ID for the OMCI
 // Managed entity EFM bonding link
-const EfmBondingLinkClassID ClassID = ClassID(419)
+const EfmBondingLinkClassID = ClassID(419) // 0x01a3
 
 var efmbondinglinkBME *ManagedEntityDefinition
 
-// EfmBondingLink (class ID #419)
+// EfmBondingLink (Class ID: #419 / 0x01a3)
 //	The EFM bonding link represents a link that can be bonded with other links to form a group. In
 //	[IEEE 802.3], a bonding group is known as a PAF and a link is known as a PME. Instances of this
 //	ME are created and deleted by the OLT.
@@ -41,17 +41,30 @@
 //
 //	Attributes
 //		Managed Entity Id
+//			This attribute uniquely identifies each instance of this ME. The two MSBs of the first byte are
+//			the bearer channel ID. Excluding the first 2-bits of the first byte, the remaining part of the
+//			ME ID is identical to that of this ME's parent PPTP xDSL UNI part 1.
+//
 //			NOTE - This attribute has the same meaning as the Stream ID in clause C.3.1.2 of [ITU-T
 //			G.998.2], except that it cannot be changed. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Associated Group Me Id
-//			Associated group ME ID: This attribute is the ME ID of the bonding group to which this link is
-//			associated. Changing this attribute moves the link from one group to another. Setting this
-//			attribute to an ME ID that has not yet been provisioned will result in this link being placed in
-//			a single-link group that contains only this link. The default value for this attribute is the
-//			null pointer, 0xFFFF. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute is the ME ID of the bonding group to which this link is associated. Changing this
+//			attribute moves the link from one group to another. Setting this attribute to an ME ID that has
+//			not yet been provisioned will result in this link being placed in a single-link group that
+//			contains only this link. The default value for this attribute is the null pointer, 0xFFFF.
+//			(R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Link Alarm Enable
+//			This bit mapped attribute enables the group down and group partial alarms. A bit value of 1
+//			means "enable".
+//
+//			Bit	Meaning
+//
+//			1 (LSB)	Link down
+//
+//			2-8	Reserved
+//
 //			(R,-W, setbycreate) (mandatory) (1-bytes)
 //
 type EfmBondingLink struct {
diff --git a/generated/efmbondinglinkperformancemonitoringhistorydata.go b/generated/efmbondinglinkperformancemonitoringhistorydata.go
index d80c83f..2ef9f2a 100644
--- a/generated/efmbondinglinkperformancemonitoringhistorydata.go
+++ b/generated/efmbondinglinkperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // EfmBondingLinkPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity EFM bonding link performance monitoring history data
-const EfmBondingLinkPerformanceMonitoringHistoryDataClassID ClassID = ClassID(422)
+const EfmBondingLinkPerformanceMonitoringHistoryDataClassID = ClassID(422) // 0x01a6
 
 var efmbondinglinkperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// EfmBondingLinkPerformanceMonitoringHistoryData (class ID #422)
+// EfmBondingLinkPerformanceMonitoringHistoryData (Class ID: #422 / 0x01a6)
 //	This ME collects PM data as seen at the xTU-C. Instances of this ME are created and deleted by
 //	the OLT.
 //
@@ -40,41 +40,39 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the EFM bonding link. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the EFM bonding link. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 and 2 MEs
 //			that contain PM threshold values. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Rx Errored Fragments
-//			Rx errored fragments: Clause 45.2.3.29 of [IEEE 802.3]. (R) (mandatory) (4-bytes)
+//			Clause 45.2.3.29 of [IEEE 802.3]. (R) (mandatory) (4-bytes)
 //
 //		Rx Small Fragments
-//			Rx small fragments: Clause 45.2.3.30 of [IEEE 802.3]. (R) (mandatory) (4-bytes)
+//			Clause 45.2.3.30 of [IEEE 802.3]. (R) (mandatory) (4-bytes)
 //
 //		Rx Large Fragments
-//			Rx large fragments: Clause 45.2.3.31 of [IEEE 802.3]. (R) (mandatory) (4-bytes)
+//			Clause 45.2.3.31 of [IEEE 802.3]. (R) (mandatory) (4-bytes)
 //
 //		Rx Discarded Fragments
-//			Rx discarded fragments: Clause 45.2.3.32 of [IEEE 802.3]. (R) (mandatory) (4-bytes)
+//			Clause 45.2.3.32 of [IEEE 802.3]. (R) (mandatory) (4-bytes)
 //
 //		Rx Fcs Errors
-//			Rx FCS errors: Clause 45.2.6.11 of [IEEE 802.3]. (R) (mandatory) (4-bytes)
+//			Clause 45.2.6.11 of [IEEE 802.3]. (R) (mandatory) (4-bytes)
 //
 //		Rx Coding Errors
-//			Rx coding errors: Clause 45.2.6.12 of [IEEE 802.3]. (R) (mandatory) (4-bytes)
+//			Clause 45.2.6.12 of [IEEE 802.3]. (R) (mandatory) (4-bytes)
 //
 //		Rx Fragments
-//			Rx fragments: Number of fragments received over this link. (R) (mandatory) (4-bytes)
+//			Number of fragments received over this link. (R) (mandatory) (4-bytes)
 //
 //		Tx Fragments
-//			Tx fragments: Number of fragments transmitted over this link. (R) (mandatory) (4-bytes)
+//			Number of fragments transmitted over this link. (R) (mandatory) (4-bytes)
 //
 type EfmBondingLinkPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/efmbondingportperformancemonitoringhistorydata.go b/generated/efmbondingportperformancemonitoringhistorydata.go
index 4186478..6585ce3 100644
--- a/generated/efmbondingportperformancemonitoringhistorydata.go
+++ b/generated/efmbondingportperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // EfmBondingPortPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity EFM bonding port performance monitoring history data
-const EfmBondingPortPerformanceMonitoringHistoryDataClassID ClassID = ClassID(423)
+const EfmBondingPortPerformanceMonitoringHistoryDataClassID = ClassID(423) // 0x01a7
 
 var efmbondingportperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// EfmBondingPortPerformanceMonitoringHistoryData (class ID #423)
+// EfmBondingPortPerformanceMonitoringHistoryData (Class ID: #423 / 0x01a7)
 //	This ME collects PM data as seen at the xTU-C. Instances of this ME are created and deleted by
 //	the OLT.
 //
@@ -40,40 +40,38 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The two MSBs of
-//			the first byte are the bearer channel ID. Excluding the first 2-bits of the first byte, the
-//			remaining part of the ME ID is identical to that of this ME's parent PPTP xDSL UNI part 1. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. The two MSBs of the first byte are
+//			the bearer channel ID. Excluding the first 2-bits of the first byte, the remaining part of the
+//			ME ID is identical to that of this ME's parent PPTP xDSL UNI part 1. (R, setbycreate)
+//			(mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 and 2 MEs
 //			that contain PM threshold values. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Rx Frames
-//			Rx frames: Number of Ethernet frames received over this port. (R) (mandatory) (4-bytes)
+//			Number of Ethernet frames received over this port. (R) (mandatory) (4-bytes)
 //
 //		Tx Frames
-//			Tx frames: Number of Ethernet frames transmitted over this port. (R) (mandatory) (4-bytes)
+//			Number of Ethernet frames transmitted over this port. (R) (mandatory) (4-bytes)
 //
 //		Rx Bytes
-//			Rx bytes: Number of bytes contained in the Ethernet frames received over this port. (R)
-//			(mandatory) (4-bytes)
+//			Number of bytes contained in the Ethernet frames received over this port. (R) (mandatory)
+//			(4-bytes)
 //
 //		Tx Bytes
-//			Tx bytes: Number of bytes contained in the Ethernet frames transmitted over this port. (R)
-//			(mandatory) (4-bytes)
+//			Number of bytes contained in the Ethernet frames transmitted over this port. (R) (mandatory)
+//			(4-bytes)
 //
 //		Tx Discarded Frames
-//			Tx discarded frames: Number of Ethernet frames discarded by the port transmit function. (R)
-//			(mandatory) (4-bytes)
+//			Number of Ethernet frames discarded by the port transmit function. (R) (mandatory) (4-bytes)
 //
 //		Tx Discarded Bytes
-//			Tx discarded bytes: Number of bytes contained in the Ethernet frames discarded by the port
-//			transmit function. (R) (mandatory) (4-bytes)
+//			Number of bytes contained in the Ethernet frames discarded by the port transmit function. (R)
+//			(mandatory) (4-bytes)
 //
 type EfmBondingPortPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/efmbondingportperformancemonitoringhistorydatapart2.go b/generated/efmbondingportperformancemonitoringhistorydatapart2.go
index 947e454..f2a1f15 100644
--- a/generated/efmbondingportperformancemonitoringhistorydatapart2.go
+++ b/generated/efmbondingportperformancemonitoringhistorydatapart2.go
@@ -27,11 +27,11 @@
 
 // EfmBondingPortPerformanceMonitoringHistoryDataPart2ClassID is the 16-bit ID for the OMCI
 // Managed entity EFM bonding port performance monitoring history data part 2
-const EfmBondingPortPerformanceMonitoringHistoryDataPart2ClassID ClassID = ClassID(424)
+const EfmBondingPortPerformanceMonitoringHistoryDataPart2ClassID = ClassID(424) // 0x01a8
 
 var efmbondingportperformancemonitoringhistorydatapart2BME *ManagedEntityDefinition
 
-// EfmBondingPortPerformanceMonitoringHistoryDataPart2 (class ID #424)
+// EfmBondingPortPerformanceMonitoringHistoryDataPart2 (Class ID: #424 / 0x01a8)
 //	This ME collects PM data as seen at the xTU-C. Instances of this ME are created and deleted by
 //	the OLT.
 //
@@ -40,66 +40,59 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The two MSBs of
-//			the first byte are the bearer channel ID. Excluding the first 2-bits of the first byte, the
-//			remaining part of the ME ID is identical to that of this ME's parent PPTP xDSL UNI part 1. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. The two MSBs of the first byte are
+//			the bearer channel ID. Excluding the first 2-bits of the first byte, the remaining part of the
+//			ME ID is identical to that of this ME's parent PPTP xDSL UNI part 1. (R, setbycreate)
+//			(mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 and 2 MEs
 //			that contain PM threshold values. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Rx Unicast Frames
-//			Rx unicast frames: Number of unicast Ethernet frames received over this port. (R) (mandatory)
-//			(4-bytes)
+//			Number of unicast Ethernet frames received over this port. (R) (mandatory) (4-bytes)
 //
 //		Tx Unicast Frames
-//			Tx unicast frames: Number of unicast Ethernet frames transmitted over this port. (R) (mandatory)
-//			(4-bytes)
+//			Number of unicast Ethernet frames transmitted over this port. (R) (mandatory) (4-bytes)
 //
 //		Rx Unicast Bytes
-//			Rx unicast bytes: Number of bytes contained in the unicast Ethernet frames received over this
-//			port. (R) (mandatory) (4-bytes)
+//			Number of bytes contained in the unicast Ethernet frames received over this port. (R)
+//			(mandatory) (4-bytes)
 //
 //		Tx Unicast Bytes
-//			Tx unicast bytes: Number of bytes contained in the unicast Ethernet frames transmitted over this
-//			port. (R) (mandatory) (4-bytes)
+//			Number of bytes contained in the unicast Ethernet frames transmitted over this port. (R)
+//			(mandatory) (4-bytes)
 //
 //		Rx Broadcast Frames
-//			Rx broadcast frames: Number of broadcast Ethernet frames received over this port. (R)
-//			(mandatory) (4-bytes)
+//			Number of broadcast Ethernet frames received over this port. (R) (mandatory) (4-bytes)
 //
 //		Tx Broadcast Frames
-//			Tx broadcast frames: Number of broadcast Ethernet frames transmitted over this port. (R)
-//			(mandatory) (4-bytes)
+//			Number of broadcast Ethernet frames transmitted over this port. (R) (mandatory) (4-bytes)
 //
 //		Rx Broadcast Bytes
-//			Rx broadcast bytes: Number of bytes contained in the broadcast Ethernet frames received over
-//			this port. (R) (mandatory) (4-bytes)
+//			Number of bytes contained in the broadcast Ethernet frames received over this port. (R)
+//			(mandatory) (4-bytes)
 //
 //		Tx Broadcast Bytes
-//			Tx broadcast bytes: Number of bytes contained in the broadcast Ethernet frames transmitted over
-//			this port. (R) (mandatory) (4-bytes)
+//			Number of bytes contained in the broadcast Ethernet frames transmitted over this port. (R)
+//			(mandatory) (4-bytes)
 //
 //		Rx Multicast Frames
-//			Rx multicast frames: Number of multicast Ethernet frames received over this port. (R)
-//			(mandatory) (4-bytes)
+//			Number of multicast Ethernet frames received over this port. (R) (mandatory) (4-bytes)
 //
 //		Tx Multicast Frames
-//			Tx multicast frames: Number of multicast Ethernet frames transmitted over this port. (R)
-//			(mandatory) (4-bytes)
+//			Number of multicast Ethernet frames transmitted over this port. (R) (mandatory) (4-bytes)
 //
 //		Rx Multicast Bytes
-//			Rx multicast bytes: Number of bytes contained in the multicast Ethernet frames received over
-//			this port. (R) (mandatory) (4-bytes)
+//			Number of bytes contained in the multicast Ethernet frames received over this port. (R)
+//			(mandatory) (4-bytes)
 //
 //		Tx Multicast Bytes
-//			Tx multicast bytes: Number of bytes contained in the multicast Ethernet frames transmitted over
-//			this port. (R) (mandatory) (4-bytes)
+//			Number of bytes contained in the multicast Ethernet frames transmitted over this port. (R)
+//			(mandatory) (4-bytes)
 //
 type EfmBondingPortPerformanceMonitoringHistoryDataPart2 struct {
 	ManagedEntityDefinition
diff --git a/generated/energyconsumptionperformancemonitoringhistorydata.go b/generated/energyconsumptionperformancemonitoringhistorydata.go
index 0b334bf..d831e3e 100644
--- a/generated/energyconsumptionperformancemonitoringhistorydata.go
+++ b/generated/energyconsumptionperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // EnergyConsumptionPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity Energy consumption performance monitoring history data
-const EnergyConsumptionPerformanceMonitoringHistoryDataClassID ClassID = ClassID(343)
+const EnergyConsumptionPerformanceMonitoringHistoryDataClassID = ClassID(343) // 0x0157
 
 var energyconsumptionperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// EnergyConsumptionPerformanceMonitoringHistoryData (class ID #343)
+// EnergyConsumptionPerformanceMonitoringHistoryData (Class ID: #343 / 0x0157)
 //	This ME collects PM data associated with the ONU's energy consumption. The time spent in various
 //	low-power states is recorded as a measure of their utility. Furthermore, the ONU may also
 //	include the equivalent of a watt-hour meter, which can be sampled from time to time to measure
@@ -44,12 +44,11 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The ME ID must
-//			be 0. (R, set-by-create) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. The ME ID must be 0. (R, set-by-
+//			create) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: No thresholds are defined for this ME. For uniformity with other PMs, the
@@ -57,22 +56,22 @@
 //			set-by-create) (mandatory) (2-bytes)
 //
 //		Doze Time
-//			Doze time: This attribute records the time during which the ONU was in doze energy conservation
-//			mode, measured in microseconds. If watchful sleep is enabled in the ONU dynamic power management
+//			This attribute records the time during which the ONU was in doze energy conservation mode,
+//			measured in microseconds. If watchful sleep is enabled in the ONU dynamic power management
 //			control ME, the ONU ignores this attribute. (R) (mandatory) (4-bytes)
 //
 //		Cyclic Sleep Time
-//			Cyclic sleep time: This attribute records the time during which the ONU was in cyclic sleep
-//			energy conservation mode, measured in microseconds. If watchful sleep is enabled in the ONU
-//			dynamic power management control ME, the ONU ignores this attribute. (R) (mandatory) (4-bytes)
+//			This attribute records the time during which the ONU was in cyclic sleep energy conservation
+//			mode, measured in microseconds. If watchful sleep is enabled in the ONU dynamic power management
+//			control ME, the ONU ignores this attribute. (R) (mandatory) (4-bytes)
 //
 //		Watchful Sleep Time
-//			Watchful sleep time: This attribute records the time during which the ONU was in watchful sleep
-//			energy conservation mode, measured in microseconds. (R) (mandatory) (4-bytes)
+//			This attribute records the time during which the ONU was in watchful sleep energy conservation
+//			mode, measured in microseconds. (R) (mandatory) (4-bytes)
 //
 //		Energy Consumed
-//			Energy consumed: This attribute records the energy consumed by the ONU, measured in millijoules.
-//			(R) (optional) (4-bytes)
+//			This attribute records the energy consumed by the ONU, measured in millijoules. (R) (optional)
+//			(4-bytes)
 //
 type EnergyConsumptionPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/enhancedfecperformancemonitoringhistorydata.go b/generated/enhancedfecperformancemonitoringhistorydata.go
index 9fb45c9..b3da774 100644
--- a/generated/enhancedfecperformancemonitoringhistorydata.go
+++ b/generated/enhancedfecperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // EnhancedFecPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity Enhanced FEC performance monitoring history data
-const EnhancedFecPerformanceMonitoringHistoryDataClassID ClassID = ClassID(453)
+const EnhancedFecPerformanceMonitoringHistoryDataClassID = ClassID(453) // 0x01c5
 
 var enhancedfecperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// EnhancedFecPerformanceMonitoringHistoryData (class ID #453)
+// EnhancedFecPerformanceMonitoringHistoryData (Class ID: #453 / 0x01c5)
 //	This ME collects PM data associated with PON downstream FEC counters for XGS-PON and subsequent
 //	ITU-T PON systems. Instances of this ME are created and deleted by the OLT.
 //
@@ -43,36 +43,34 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the ANI-G or a TWDM channel. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the ANI-G or a TWDM channel. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 64 Bit Id
 //			Threshold data 64-bit ID: This attribute points to an instance of the threshold data 64-bit ME
 //			that contains PM threshold values. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Corrected Bytes
-//			Corrected bytes: This attribute counts the number of bytes that were corrected by the FEC
-//			function. (R) (mandatory) (8-bytes)
+//			This attribute counts the number of bytes that were corrected by the FEC function. (R)
+//			(mandatory) (8-bytes)
 //
 //		Corrected Code Words
-//			Corrected code words: This attribute counts the code words that were corrected by the FEC
-//			function. (R) (mandatory) (8-bytes)
+//			This attribute counts the code words that were corrected by the FEC function. (R) (mandatory)
+//			(8-bytes)
 //
 //		Uncorrectable Code Words
-//			Uncorrectable code words: This attribute counts errored code words that could not be corrected
-//			by the FEC function. (R) (mandatory) (8-bytes)
+//			This attribute counts errored code words that could not be corrected by the FEC function. (R)
+//			(mandatory) (8-bytes)
 //
 //		Total Code Words
-//			Total code words: This attribute counts the total received code words. (R) (mandatory) (8-bytes)
+//			This attribute counts the total received code words. (R) (mandatory) (8-bytes)
 //
 //		Fec Seconds
-//			FEC seconds:	This attribute counts seconds during which there was an FEC anomaly. (R)
-//			(mandatory) (2-bytes)
+//			This attribute counts seconds during which there was an FEC anomaly. (R) (mandatory) (2-bytes)
 //
 type EnhancedFecPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/enhancedsecuritycontrol.go b/generated/enhancedsecuritycontrol.go
index af3fa3c..7c2948a 100644
--- a/generated/enhancedsecuritycontrol.go
+++ b/generated/enhancedsecuritycontrol.go
@@ -27,11 +27,11 @@
 
 // EnhancedSecurityControlClassID is the 16-bit ID for the OMCI
 // Managed entity Enhanced security control
-const EnhancedSecurityControlClassID ClassID = ClassID(332)
+const EnhancedSecurityControlClassID = ClassID(332) // 0x014c
 
 var enhancedsecuritycontrolBME *ManagedEntityDefinition
 
-// EnhancedSecurityControl (class ID #332)
+// EnhancedSecurityControl (Class ID: #332 / 0x014c)
 //	This ME contains the capabilities, parameters and controls of enhanced GPON security features
 //	when they are negotiated via the OMCI (Note). The attributes in this ME are intended to be used
 //	to implement a symmetric-key-based three step authentication process as described in the
@@ -45,33 +45,79 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. There is only
-//			one instance, number 0. (R) (mandatory) (2 bytes)
+//			This attribute uniquely identifies each instance of this ME. There is only one instance, number
+//			0. (R) (mandatory) (2 bytes)
 //
 //		Olt Crypto Capabilities
+//			This attribute specifies the cryptographic mechanisms available at the OLT. It is written by the
+//			OLT during authentication step 1. It is formatted as a bit map, where a 1 bit indicates that the
+//			particular algorithm is supported, and a 0 bit indicates it is not supported.
+//
+//			Bit position	Algorithm
+//
+//			1 (LSB)	AES-CMAC-128 (support is mandatory)
+//
+//			2 	HMAC-SHA-256
+//
+//			3 	HMAC-SHA-512
+//
+//			4-128 	Reserved
+//
 //			(W) (mandatory) (16 bytes)
 //
 //		Olt Random Challenge Table
+//			This attribute specifies the random challenge OLT_challenge issued by the OLT during
+//			authentication step 1. It is structured as a table, with each entry being 17 bytes. The first
+//			byte is the table row number, starting at 1, and the remaining 16 bytes are the contents of the
+//			entry. OLT_challenge is the concatenation of all 16-byte content fields. In normal use, the OLT
+//			will write all the entries in the table, and then trigger the ONU's processing of the entire
+//			table using the OLT challenge status attribute. The table size is known by the maximum index set
+//			by the OLT. The OLT can clear the table with a set operation to row 0. (R, W) (mandatory) (17 *
+//			N-bytes)
+//
 //			NOTE - It is assumed that the length of OLT_challenge is always an integer multiple of 16-bytes.
 //
 //		Olt Challenge Status
+//			This Boolean attribute controls the completion of authentication step 1. This attribute behaves
+//			as follows.
+//
+//			When the OLT performs the first of possibly several set operations to the OLT crypto
+//			capabilities or the OLT random challenge table attributes, a side effect of the set operation is
+//			that the ONU sets the OLT challenge status attribute to false.
+//
+//			When the OLT completes the set operation(s) to the OLT crypto capabilities and the OLT random
+//			challenge table attributes, then it sets the OLT challenge status attribute to true. This
+//			triggers the ONU to process the OLT random challenge table, using its choice of the OLT's
+//			candidate cryptographic hash algorithms.
+//
 //			The ONU initializes this attribute to the value false. (R, W) (mandatory) (1-byte)
 //
 //		Onu Selected Crypto Capabilities
-//			ONU selected crypto capabilities: This attribute specifies the cryptographic capability selected
-//			by the ONU in authentication step 2. Its value specifies one of the bit positions that has the
-//			value 1 in the OLT crypto capabilities attribute. (R) (mandatory) (1 byte)
+//			This attribute specifies the cryptographic capability selected by the ONU in authentication step
+//			2. Its value specifies one of the bit positions that has the value 1 in the OLT crypto
+//			capabilities attribute. (R) (mandatory) (1 byte)
 //
 //		Onu Random Challenge Table
-//			ONU random challenge table: This attribute specifies the random challenge ONU_challenge issued
-//			by the ONU during authentication step 2. It is structured as a table, with each entry being
-//			16-bytes of content. ONU_challenge is the concatenation of all 16-byte content fields in the
-//			table. Once the OLT triggers a response to be generated using the OLT challenge status
-//			attribute, the ONU generates the response and writes the table (in a single operation). The AVC
-//			generated by this attribute signals to the OLT that the challenge is ready, so that the OLT can
-//			commence a get/get-next sequence to obtain the table's contents. (R) (mandatory) (16 * P-bytes)
+//			This attribute specifies the random challenge ONU_challenge issued by the ONU during
+//			authentication step 2. It is structured as a table, with each entry being 16-bytes of content.
+//			ONU_challenge is the concatenation of all 16-byte content fields in the table. Once the OLT
+//			triggers a response to be generated using the OLT challenge status attribute, the ONU generates
+//			the response and writes the table (in a single operation). The AVC generated by this attribute
+//			signals to the OLT that the challenge is ready, so that the OLT can commence a get/get-next
+//			sequence to obtain the table's contents. (R) (mandatory) (16 * P-bytes)
 //
 //		Onu Authentication Result Table
+//			(authentication step 2). This attribute contains the result of the authentication computation
+//			from the ONU (ONU_result), according to the ONU's selected crypto capabilities attribute.
+//
+//			ONU_result-= SelectedHashFunction (PSK, (ONU_selected_crypto capabilities | OLT_challenge |
+//			ONU_challenge | 0x0000 0000 0000 0000)),
+//
+//			where "|" denotes concatenation.
+//
+//			This attribute is structured as a table, with each entry being 16 bytes of content. The number
+//			of rows Q is implicit in the choice of hash algorithm.
+//
 //			Once the OLT triggers a response to be generated using the OLT challenge status attribute, the
 //			ONU generates ONU_result and writes the table (in a single operation). The AVC generated by this
 //			attribute signals to the OLT that the response is ready, so that the OLT can commence a get/get-
@@ -85,23 +131,107 @@
 //			rows R is implicit in the choice of hash algorithm. The OLT can clear the table with a set
 //			operation to row 0. (W) (mandatory) (17 * R-bytes)
 //
+//			This attribute is used in authentication step 3. It contains OLT_result, the result of the
+//			authentication computation from the OLT.
+//
+//			OLT_result-= SelectedHashFunction (PSK, (ONU_selected_crypto capabilities | ONU_challenge |
+//			OLT_challenge | ONU_serial_number)).
+//
+//			The ONU_serial_number is the serial number attribute of the ONU-G ME, 8 bytes.
+//
 //		Olt Result Status
+//			(authentication step 3). This Boolean attribute controls and reports the status of the OLT
+//			authentication result table attribute. This attribute behaves as follows.
+//
+//			When the OLT performs the first of possibly several set operations to the OLT authentication
+//			result table attribute, a side effect of the set operation is that the ONU sets the OLT result
+//			status attribute to false.
+//
+//			When the OLT completes the set operation(s) to the OLT authentication result table, then it sets
+//			the OLT result status attribute to true. This triggers the ONU to process the OLT authentication
+//			result table.
+//
 //			(R, W) (mandatory) (1 byte)
 //
 //		Onu Authentication Status
+//			This attribute indicates the status of the authentication relationship from the perspective of
+//			the ONU. It has the following values.
+//
+//			0	Indeterminate. This initial value indicates that the OMCI authentication process has not yet
+//			completed, and may not even have been started.
+//
+//			1	Reserved.
+//
+//			2	Reserved.
+//
+//			3	Authentication success: the procedure has completed at least once since the latest ONU
+//			activation and in its most recent execution, the ONU has authenticated the OLT.
+//
+//			4	Authentication failure: the procedure has completed at least once since the latest ONU
+//			activation, and either its most recent execution resulted in an error or the ONU has failed to
+//			authenticate the OLT.
+//
+//			5	Reserved.
+//
+//			Upon ONU activation, the ONU sets the attribute to the initial value. When the ONU
+//			authentication status has the value 3, encryption keys exchanged in the TC layer will be
+//			encrypted using the master session key (ITUT G.984 systems) or the key encryption key (KEK,
+//			ITU-T G.987 systems). The OLT should check the value of this attribute before initiating a key
+//			switch.
+//
 //			(R) (mandatory) (1 byte)
 //
 //		Master Session Key Name
+//			Following successful authentication, this register contains the "name," or the hash signature,
+//			of the current master session key. The master session key is defined as:
+//
+//			MSK-= SelectedHashFunction (PSK, (OLT_challenge | ONU_challenge)).
+//
+//			The master session key name is defined as:
+//
+//			MSKname-= SelectedHashFunction (PSK, (ONU_challenge | OLT_challenge | 0x 3141 5926 5358 9793
+//			3141 5926 5358 9793)).
+//
+//			If the selected hash function generates more than 128 bits, the result is truncated to the
+//			leftmost (most significant) 128 bits.
+//
 //			Upon the invalidation of a master session key (e.g., due to an ONU reset or deactivation, or due
 //			to an ONU-local decision that the master session key has expired), the ONU sets the master
 //			session key name to all zeros. (R) (mandatory) (16 bytes)
 //
 //		Broadcast Key Table
+//			10	Clear the entire table.
+//
+//			11	Reserved.
+//
+//			The four MSBs specify the length of the fragment, which is left-justified in the key fragment
+//			field. The value 0 indicates 16-bytes of key fragment.
+//
+//			The other two bits are reserved.
+//
+//			Row identifier (1 byte): The two MSBs of this field are the key index, which appears in the
+//			header of encrypted multicast GEM frames. Key index 0 always indicates cleartext, and should
+//			therefore not appear in the identifier. The four LSBs identify the key fragment number, starting
+//			with 0. The other two bits are reserved.
+//
+//			Key fragment (16 bytes): This field contains the specified fragment of the key (encrypted with
+//			AES-ECB using the KEK).
+//
 //			(R, W) (optional) (18N bytes)
 //
+//			This attribute is defined only in ITU-T G.987 systems. It contains the broadcast key generated
+//			by the OLT. It is a table, each of whose rows is structured as follows.
+//
+//			Row control (1 byte): The two LSBs of this byte determine the attribute's behaviour under the
+//			set action. They always read back as 0 under the get next action.
+//
+//			00	Set the specified row.
+//
+//			01	Clear the specified row.
+//
 //		Effective Key Length
-//			Effective key length: This attribute specifies the maximum effective length, in bits, of keys
-//			generated by the ONU. (R) (optional) (2 bytes)
+//			This attribute specifies the maximum effective length, in bits, of keys generated by the ONU.
+//			(R) (optional) (2 bytes)
 //
 type EnhancedSecurityControl struct {
 	ManagedEntityDefinition
diff --git a/generated/enhancedtcperformancemonitoringhistorydata.go b/generated/enhancedtcperformancemonitoringhistorydata.go
index aa80d5f..ddc1605 100644
--- a/generated/enhancedtcperformancemonitoringhistorydata.go
+++ b/generated/enhancedtcperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // EnhancedTcPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity Enhanced TC performance monitoring history data
-const EnhancedTcPerformanceMonitoringHistoryDataClassID ClassID = ClassID(454)
+const EnhancedTcPerformanceMonitoringHistoryDataClassID = ClassID(454) // 0x01c6
 
 var enhancedtcperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// EnhancedTcPerformanceMonitoringHistoryData (class ID #454)
+// EnhancedTcPerformanceMonitoringHistoryData (Class ID: #454 / 0x01c6)
 //	This ME collects PM data associated with the XGS-PON and subsequent ITU-T PON systems' TC layer.
 //
 //	For a complete discussion of generic PM architecture, refer to clause I.4.
@@ -41,50 +41,62 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the ANI-G. (R, set-by-create)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the ANI-G. (R, set-by-create) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 64 Bit Id
 //			Threshold data 64-bit ID: This attribute points to an instance of the threshold data 64-bit ME
 //			that contains PM threshold values. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Psbd Hec Error Count
-//			PSBd HEC error count: This attribute counts HEC errors in any of the fields of the downstream
-//			physical sync block. (R) (optional) (4-bytes)
+//			This attribute counts HEC errors in any of the fields of the downstream physical sync block. (R)
+//			(optional) (4-bytes)
 //
 //		Xgtc Hec Error Count
-//			XGTC HEC error count: This attribute counts HEC errors detected in the XGTC header. In [ITU-T
-//			G.9807.1], this attribute is used for FS HEC error count management. (R) (optional) (4-bytes)
+//			This attribute counts HEC errors detected in the XGTC header. In [ITU-T G.9807.1], this
+//			attribute is used for FS HEC error count management. (R) (optional) (4-bytes)
 //
 //		Unknown Profile Count
-//			Unknown profile count: This attribute counts the number of grants received whose specified
-//			profile was not known to the ONU. (R) (optional) (4-bytes)
+//			This attribute counts the number of grants received whose specified profile was not known to the
+//			ONU. (R) (optional) (4-bytes)
 //
 //		Transmitted Xgem Frames
-//			Transmitted XGEM frames: This attribute counts the number of non-idle XGEM frames transmitted.
-//			If an SDU is fragmented, each fragment is an XGEM frame and is counted as such. (R) (mandatory)
-//			(8 bytes)
+//			This attribute counts the number of non-idle XGEM frames transmitted. If an SDU is fragmented,
+//			each fragment is an XGEM frame and is counted as such. (R) (mandatory) (8 bytes)
 //
 //		Fragment Xgem Frames
-//			Fragment XGEM frames: This attribute counts the number of XGEM frames that represent fragmented
-//			SDUs, as indicated by the LF bit = 0. (R) (optional) (8-bytes)
+//			This attribute counts the number of XGEM frames that represent fragmented SDUs, as indicated by
+//			the LF bit = 0. (R) (optional) (8-bytes)
 //
 //		Xgem Hec Lost Words Count
-//			XGEM HEC lost words count: This attribute counts the number of 4-byte words lost because of an
-//			XGEM frame HEC error. In general, all XGTC payload following the error is lost, until the next
-//			PSBd event. (R) (optional) (8 bytes)
+//			This attribute counts the number of 4-byte words lost because of an XGEM frame HEC error. In
+//			general, all XGTC payload following the error is lost, until the next PSBd event. (R) (optional)
+//			(8 bytes)
 //
 //		Xgem Key Errors
+//			This attribute counts the number of downstream XGEM frames received with an invalid key
+//			specification. The key may be invalid for several reasons, among which are:
+//
+//			a)	GEM port provisioned for clear text and key index not equal to 00;
+//
+//			b)	no multicast key of the specified key index has been provided via the OMCI for a multicast
+//			GEM port;
+//
+//			c)	no unicast key of the specified key index has been successfully negotiated (see clause 15.5
+//			of [ITU-T G.987.3] or clause C.15.5 of [ITU-T G.9807.1] for key negotiation state machine);
+//
+//			d)	GEM port specified to be encrypted and key index = 00;
+//
+//			e)	key index = 11, a reserved value.
+//
 //			(R) (mandatory) (8 bytes)
 //
 //		Xgem Hec Error Count
-//			XGEM HEC error count: This attribute counts the number of instances of an XGEM frame HEC error.
-//			(R) (mandatory) (8 bytes)
+//			This attribute counts the number of instances of an XGEM frame HEC error. (R) (mandatory) (8
+//			bytes)
 //
 //		Transmitted Bytes In Non_Idle Xgem Frames
 //			Transmitted bytes in non-idle XGEM frames: This attribute counts the number of transmitted bytes
@@ -95,16 +107,14 @@
 //			non-idle XGEM frames. (R) (optional) (8 bytes)
 //
 //		Lods Event Count
-//			LODS event count: This attribute counts the number of state transitions from O5.1 to O6. (R)
-//			(optional) (4-bytes)
+//			This attribute counts the number of state transitions from O5.1 to O6. (R) (optional) (4-bytes)
 //
 //		Lods Event Restored Count
-//			LODS event restored count: This attribute counts the number of LODS cleared events. (R)
-//			(optional) (4-bytes)
+//			This attribute counts the number of LODS cleared events. (R) (optional) (4-bytes)
 //
 //		Onu Reactivation By Lods Events
-//			ONU reactivation by LODS events: This attribute counts the number of LODS events resulting in
-//			ONU reactivation without synchronization being reacquired. (R) (optional) (4-bytes)
+//			This attribute counts the number of LODS events resulting in ONU reactivation without
+//			synchronization being reacquired. (R) (optional) (4-bytes)
 //
 type EnhancedTcPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/epondownstreamperformancemonitoringconfiguration.go b/generated/epondownstreamperformancemonitoringconfiguration.go
new file mode 100644
index 0000000..8ee5afc
--- /dev/null
+++ b/generated/epondownstreamperformancemonitoringconfiguration.go
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+/*
+ * NOTE: This file was generated, manual edits will be overwritten!
+ *
+ * Generated by 'goCodeGenerator.py':
+ *              https://github.com/cboling/OMCI-parser/README.md
+ */
+
+package generated
+
+import "github.com/deckarep/golang-set"
+
+// EponDownstreamPerformanceMonitoringConfigurationClassID is the 16-bit ID for the OMCI
+// Managed entity EPON downstream performance monitoring configuration
+const EponDownstreamPerformanceMonitoringConfigurationClassID = ClassID(406) // 0x0196
+
+var epondownstreamperformancemonitoringconfigurationBME *ManagedEntityDefinition
+
+// EponDownstreamPerformanceMonitoringConfiguration (Class ID: #406 / 0x0196)
+//	This ME represents window sizes and threshold values for EPON downstream PM operations which are
+//	defined in [IEEE 802.3] as: errored symbol period, errored frame, errored frame period and
+//	errored frame seconds summary.
+//
+//	The EPON ONU automatically instantiates an instance of this ME for each ANI-E.
+//
+//	Relationships
+//		An instance of this ME is associated with an ANI-E.
+//
+//	Attributes
+//		Managed Entity Id
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the ANI-E. (R, set-by-create) (mandatory) (2-bytes)
+//
+//		Errored Symbol Period Window
+//			This attribute specifies the number of symbols in the measurement period, as defined in clause
+//			57.5.3.1 of [IEEE 802.3]. (R, W) (optional) (8-bytes)
+//
+//		Errored Symbol Period Threshold
+//			This attribute specifies the threshold of errored symbols for generating an event report, as
+//			defined in clause 57.5.3.1 of [IEEE 802.3]. (R, W) (optional) (8-bytes)
+//
+//		Errored Frame Window
+//			This attribute specifies the duration in units of 100-ms of the measurement period, as defined
+//			in clause 57.5.3.2 of [IEEE 802.3]. (R, W) (optional) (2-bytes)
+//
+//		Errored Frame Threshold
+//			This attribute specifies the threshold of errored frames for generating an event report, as
+//			defined in clause 57.5.3.2 of [IEEE 802.3]. (R, W) (optional) (4-bytes)
+//
+//		Errored Frame Period Window
+//			This attribute specifies the duration in terms of frames of the measurement period, as defined
+//			in clause 57.5.3.3 of [IEEE 802.3]. (R, W) (optional) (4-bytes)
+//
+//		Errored Frame Period Threshold
+//			This attribute specifies the threshold of errored frames for generating an event report, as
+//			defined in clause 57.5.3.3 of [IEEE 802.3]. (R, W) (optional) (4-bytes)
+//
+//		Errored Frame Seconds Summary Window
+//			This attribute specifies the duration in units of 100ms of the measurement period, as defined in
+//			clause-57.5.3.4 of [IEEE-802.3]. (R, W) (optional) (2-bytes)
+//
+//		Errored Frame Seconds Summary Threshold
+//			This attribute specifies the threshold of errored frame seconds for generating an event report,
+//			as defined in clause 57.5.3.4 of [IEEE 802.3]. (R, W) (optional) (2-bytes)
+//
+type EponDownstreamPerformanceMonitoringConfiguration struct {
+	ManagedEntityDefinition
+	Attributes AttributeValueMap
+}
+
+func init() {
+	epondownstreamperformancemonitoringconfigurationBME = &ManagedEntityDefinition{
+		Name:    "EponDownstreamPerformanceMonitoringConfiguration",
+		ClassID: 406,
+		MessageTypes: mapset.NewSetWith(
+			Get,
+			Set,
+		),
+		AllowedAttributeMask: 0xff00,
+		AttributeDefinitions: AttributeDefinitionMap{
+			0: Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read, SetByCreate), false, false, false, 0),
+			1: Uint64Field("ErroredSymbolPeriodWindow", UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read, Write), false, true, false, 1),
+			2: Uint64Field("ErroredSymbolPeriodThreshold", UnsignedIntegerAttributeType, 0x4000, 0, mapset.NewSetWith(Read, Write), false, true, false, 2),
+			3: Uint16Field("ErroredFrameWindow", UnsignedIntegerAttributeType, 0x2000, 0, mapset.NewSetWith(Read, Write), false, true, false, 3),
+			4: Uint32Field("ErroredFrameThreshold", UnsignedIntegerAttributeType, 0x1000, 0, mapset.NewSetWith(Read, Write), false, true, false, 4),
+			5: Uint32Field("ErroredFramePeriodWindow", UnsignedIntegerAttributeType, 0x0800, 0, mapset.NewSetWith(Read, Write), false, true, false, 5),
+			6: Uint32Field("ErroredFramePeriodThreshold", UnsignedIntegerAttributeType, 0x0400, 0, mapset.NewSetWith(Read, Write), false, true, false, 6),
+			7: Uint16Field("ErroredFrameSecondsSummaryWindow", UnsignedIntegerAttributeType, 0x0200, 0, mapset.NewSetWith(Read, Write), false, true, false, 7),
+			8: Uint16Field("ErroredFrameSecondsSummaryThreshold", UnsignedIntegerAttributeType, 0x0100, 0, mapset.NewSetWith(Read, Write), false, true, false, 8),
+		},
+		Access:  CreatedByOnu,
+		Support: UnknownSupport,
+	}
+}
+
+// NewEponDownstreamPerformanceMonitoringConfiguration (class ID 406) creates the basic
+// Managed Entity definition that is used to validate an ME of this type that
+// is received from or transmitted to the OMCC.
+func NewEponDownstreamPerformanceMonitoringConfiguration(params ...ParamData) (*ManagedEntity, OmciErrors) {
+	return NewManagedEntity(*epondownstreamperformancemonitoringconfigurationBME, params...)
+}
diff --git a/generated/equipmentextensionpackage.go b/generated/equipmentextensionpackage.go
index 1deabe7..22bca67 100644
--- a/generated/equipmentextensionpackage.go
+++ b/generated/equipmentextensionpackage.go
@@ -27,11 +27,11 @@
 
 // EquipmentExtensionPackageClassID is the 16-bit ID for the OMCI
 // Managed entity Equipment extension package
-const EquipmentExtensionPackageClassID ClassID = ClassID(160)
+const EquipmentExtensionPackageClassID = ClassID(160) // 0x00a0
 
 var equipmentextensionpackageBME *ManagedEntityDefinition
 
-// EquipmentExtensionPackage (class ID #160)
+// EquipmentExtensionPackage (Class ID: #160 / 0x00a0)
 //	This ME supports optional extensions to circuit pack MEs. If the circuit pack supports these
 //	features, the ONU creates and deletes this ME along with its associated real or virtual circuit
 //	pack.
@@ -41,16 +41,46 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the ONU-G or cardholder. (R)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the ONU-G or cardholder. (R) (mandatory) (2-bytes)
 //
 //		Environmental Sense
+//			This attribute provisions an ONU that supports external sense points, e.g., physical security
+//			detectors at an enclosure. Each pair of bits is defined as follows.
+//
+//			00	Sense point disabled (default)
+//
+//			01	Report contact closure
+//
+//			10	Report contact open
+//
+//			11	Sense point disabled (same as 00)
+//
+//			If the byte is represented in binary as 0B hhgg ffee ddcc bbaa, bits hh correspond to sense
+//			point 1, while bits aa correspond to sense point 8. (R,-W) (optional) (2-bytes)
+//
 //			NOTE - Some specific sense point applications are already defined on the ONU-G ME. It is the
 //			vendor's choice how to configure and report sense points that appear both generically and
 //			specifically.
 //
 //		Contact Closure Output
+//			This attribute provisions an ONU that supports external contact closure outputs, e.g., sump pump
+//			or air conditioner activation at an ONU enclosure. A contact point is said to be released when
+//			it is not energized. Whether this corresponds to an open or a closed electrical circuit depends
+//			on the ONU's wiring options. Upon ONU initialization, all contact points should go to the
+//			released state.
+//
+//			If the byte is represented in binary as 0B hhgg ffee ddcc bbaa, bits hh correspond to contact
+//			output point 1, while bits aa correspond to contact output point 8.
+//
+//			On write, the bits of this attribute have the following meaning.
+//
+//			0x	No change to contact output point state
+//
+//			10	Release contact output point
+//
+//			11	Operate contact output point
+//
 //			On read, the left bit in each pair should be set to 0 at the ONU and ignored at the OLT. The
 //			right bit indicates a released output point with 0 and an operated contact point with 1. (R,-W)
 //			(optional) (2-bytes)
diff --git a/generated/ethernetflowterminationpoint.go b/generated/ethernetflowterminationpoint.go
index 67296f6..d2401d8 100644
--- a/generated/ethernetflowterminationpoint.go
+++ b/generated/ethernetflowterminationpoint.go
@@ -27,11 +27,11 @@
 
 // EthernetFlowTerminationPointClassID is the 16-bit ID for the OMCI
 // Managed entity Ethernet flow termination point
-const EthernetFlowTerminationPointClassID ClassID = ClassID(286)
+const EthernetFlowTerminationPointClassID = ClassID(286) // 0x011e
 
 var ethernetflowterminationpointBME *ManagedEntityDefinition
 
-// EthernetFlowTerminationPoint (class ID #286)
+// EthernetFlowTerminationPoint (Class ID: #286 / 0x011e)
 //	The Ethernet flow TP contains the attributes necessary to originate and terminate Ethernet
 //	frames in the ONU. It is appropriate when transporting pseudowire services via layer-2.
 //	Instances of this ME are created and deleted by the OLT.
@@ -42,28 +42,39 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to a pseudowire TP ME. (R, setbycreate) (mandatory)
-//			(2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to a pseudowire TP ME. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Destination Mac
-//			Destination MAC: This attribute specifies the destination MAC address of upstream Ethernet
-//			frames. (R,-W, setbycreate) (mandatory) (6-bytes)
+//			This attribute specifies the destination MAC address of upstream Ethernet frames. (R,-W,
+//			setbycreate) (mandatory) (6-bytes)
 //
 //		Source Mac
-//			Source MAC: This attribute specifies the near-end MAC address. It is established by nonOMCI
-//			means (e.g., factory programmed into ONU flash memory) and is included here for information
-//			only. (R) (mandatory) (6-bytes)
+//			This attribute specifies the near-end MAC address. It is established by nonOMCI means (e.g.,
+//			factory programmed into ONU flash memory) and is included here for information only. (R)
+//			(mandatory) (6-bytes)
 //
 //		Tag Policy
+//			0	untagged frame
+//
+//			1	tagged frame
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
+//			This attribute specifies the tagging policy to be applied to upstream Ethernet frames.
+//
 //		Tci
-//			TCI:	If the tag policy calls for tagging of upstream Ethernet frames, this attribute specifies
-//			the tag control information, which includes the VLAN tag, P bits and CFI bit. (R,-W) (optional)
+//			If the tag policy calls for tagging of upstream Ethernet frames, this attribute specifies the
+//			tag control information, which includes the VLAN tag, P bits and CFI bit. (R,-W) (optional)
 //			(2-bytes)
 //
 //		Loopback
+//			This attribute sets the loopback configuration as follows.
+//
+//			0	No loopback
+//
+//			1	Loopback of downstream traffic at MAC client
+//
 //			(R,-W) (mandatory) (1-byte)
 //
 type EthernetFlowTerminationPoint struct {
diff --git a/generated/ethernetframeextendedpm.go b/generated/ethernetframeextendedpm.go
index 6ff360c..bad6912 100644
--- a/generated/ethernetframeextendedpm.go
+++ b/generated/ethernetframeextendedpm.go
@@ -27,11 +27,11 @@
 
 // EthernetFrameExtendedPmClassID is the 16-bit ID for the OMCI
 // Managed entity Ethernet frame extended PM
-const EthernetFrameExtendedPmClassID ClassID = ClassID(334)
+const EthernetFrameExtendedPmClassID = ClassID(334) // 0x014e
 
 var ethernetframeextendedpmBME *ManagedEntityDefinition
 
-// EthernetFrameExtendedPm (class ID #334)
+// EthernetFrameExtendedPm (Class ID: #334 / 0x014e)
 //	This ME collects some of the PM data at a point where an Ethernet flow can be observed. It is
 //	based on the Etherstats group of [IETF RFC 2819]. Instances of this ME are created and deleted
 //	by the OLT. References to received frames are to be interpreted as the number of frames entering
@@ -45,78 +45,158 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. To facilitate
-//			discovery, the identification of instances sequentially starting with 1 is encouraged. (R,
-//			setbycreate) (mandatory) (2 bytes)
+//			This attribute uniquely identifies each instance of this ME. To facilitate discovery, the
+//			identification of instances sequentially starting with 1 is encouraged. (R, setbycreate)
+//			(mandatory) (2 bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. If
-//			continuous accumulation is enabled in the control block, this attribute is not used and has the
-//			fixed value 0. (R) (mandatory) (1 byte)
+//			This attribute identifies the most recently finished 15-min interval. If continuous accumulation
+//			is enabled in the control block, this attribute is not used and has the fixed value 0. (R)
+//			(mandatory) (1 byte)
 //
 //		Control Block
+//			This attribute contains fields defined as follows.+
+//
+//			Threshold data 1/2 ID: (2 bytes) This attribute points to an instance of the threshold data 1 ME
+//			that contains PM threshold values. Since no threshold value attribute number exceeds 7, a
+//			threshold data 2 ME is optional. When PM is collected on a continuously running basis, rather
+//			than in 15-min intervals, counter thresholds should not be established. There is no mechanism to
+//			clear a TCA, and any counter parameter may eventually be expected to cross any given threshold
+//			value.
+//
+//			Parent ME class: (2 bytes) This field contains the enumerated value of the ME class of the PM
+//			ME's parent. Together with the parent ME instance field, this permits a given PM ME to be
+//			associated with any OMCI ME. The supported ME classes are as follows.
+//
+//			46	MAC bridge configuration data
+//
+//			47	MAC bridge port configuration data
+//
+//			11	Physical path termination point Ethernet UNI
+//
+//			98	Physical path termination point xDSL UNI part 1
+//
+//			266	GEM IW termination point
+//
+//			281	Multicast GEM IW termination point
+//
+//			329	Virtual Ethernet interface point
+//
+//			162	Physical path termination point MoCA UNI
+//
+//			Parent ME instance: (2 bytes) This field identifies the specific parent ME instance to which the
+//			PM ME is attached.
+//
+//			Accumulation disable: (2 bytes) This bit field allows PM accumulation to be disabled; refer to
+//			Table 9.3.32-1. The default value 0 enables PM collection. If bit 15 is set to 1, no PM is
+//			collected by this ME instance. If bit 15-=-0 and any of bits 14..1 are set to 1, PM collection
+//			is inhibited for the attributes indicated by the 1 bits. Inhibiting PM collection does not
+//			change the value of a PM attribute, but if PM is accumulated in 15-min intervals, the value is
+//			lost at the next 15-min interval boundary.
+//
+//			Bit 16 is an action bit that always reads back as 0. When written to 1, it resets all PM
+//			attributes in the ME, and clears any TCAs that may be outstanding.
+//
+//			TCA disable: (2 bytes). Also clarified in Table 9.3.32-1, this field permits TCAs to be
+//			inhibited, either individually or for the complete ME instance. As with the accumulation disable
+//			field, the default value 0 enables TCAs, and setting the global disable bit overrides the
+//			settings of the individual thresholds. Unlike the accumulation disable field, the bits are
+//			mapped to the thresholds defined in the associated threshold data 1 and 2 ME instances. When the
+//			global or attribute-specific value changes from 0 to 1, outstanding TCAs are cleared, either for
+//			the ME instance globally or for the individual disabled threshold. These bits affect only
+//			notifications, not the underlying parameter accumulation or storage.
+//
+//			If the threshold data 1/2 ID attribute does not contain a valid pointer, this field is not
+//			meaningful.
+//
+//			Thresholds should be used with caution if PM attributes are accumulated continuously.
+//
+//			Control fields: (2 bytes). This field is a bit map whose values govern the behaviour of the PM
+//			ME. Bits are assigned as follows.
+//
+//			Bit 1 (LSB)	The value 1 specifies continuous accumulation, regardless of 15-min intervals. There
+//			is no concept of current and historical accumulators; get and get current data (if supported)
+//			both return current values. The value 0 specifies 15-min accumulators exactly like those of
+//			classical PM.
+//
+//			Bit 2	This bit indicates directionality for the collection of data. The value 0 indicates that
+//			data are to be collected for upstream traffic. The value 1 indicates that data are to be
+//			collected for downstream traffic.
+//
+//			Bits 3..14	Reserved, should be set to 0 by the OLT and ignored by the ONU.
+//
+//			Bit 15	When this bit is 1, the P bits of the TCI field are used to filter the PM data collected.
+//			The value 0 indicates that PM is collected without regard to P bits.
+//
+//			Bit 16	When this bit is 1, the VID bits of the TCI field are used to filter the PM data
+//			collected. The value 0 indicates that PM is collected without regard to VID.
+//
+//			TCI: (2 bytes). This field contains the value optionally used as a filter for the PM data
+//			collected, under the control of bits 15..16 of the control fields. This value is matched to the
+//			outer tag of a frame. Untagged frames are not counted when this field is used.
+//
+//			Reserved: (2 bytes). Not used; should be set to 0 by the OLT and ignored by the ONU.
+//
 //			(R, W, setbycreate) (mandatory) (16 bytes)
 //
 //		Drop Events
-//			Drop events:	The total number of events in which frames were dropped due to a lack of resources.
-//			This is not necessarily the number of frames dropped; it is the number of times this event was
-//			detected. (R) (mandatory) (4 bytes)
-//
-//		Octets
-//			Octets:	The total number of octets received, including those in bad frames, excluding framing
-//			bits, but including FCS. (R) (mandatory) (4 bytes)
-//
-//		Frames
-//			Frames:	The total number of frames received, including bad frames, broadcast frames and
-//			multicast frames. (R) (mandatory) (4 bytes)
-//
-//		Broadcast Frames
-//			Broadcast frames: The total number of received good frames directed to the broadcast address.
-//			This does not include multicast frames. (R) (mandatory) (4 bytes)
-//
-//		Multicast Frames
-//			Multicast frames: The total number of received good frames directed to a multicast address. This
-//			does not include broadcast frames. (R) (mandatory) (4 bytes)
-//
-//		Crc Errored Frames
-//			CRC errored frames: The total number of frames received that had a length (excluding framing
-//			bits, but including FCS octets) of between 64 and 1518 octets, inclusive, but had either a bad
-//			FCS with an integral number of octets (FCS error) or a bad FCS with a non-integral number of
-//			octets (alignment error). (R) (mandatory) (4 bytes)
-//
-//		Undersize Frames
-//			Undersize frames: The total number of frames received that were less than 64 octets long but
-//			were otherwise well formed (excluding framing bits, but including FCS octets). (R) (mandatory)
-//			(4 bytes)
-//
-//		Oversize Frames
-//			Oversize frames: The total number of frames received that were longer than 1518 octets
-//			(excluding framing bits, but including FCS octets) and were otherwise well formed. (R)
+//			The total number of events in which frames were dropped due to a lack of resources. This is not
+//			necessarily the number of frames dropped; it is the number of times this event was detected. (R)
 //			(mandatory) (4 bytes)
 //
+//		Octets
+//			The total number of octets received, including those in bad frames, excluding framing bits, but
+//			including FCS. (R) (mandatory) (4 bytes)
+//
+//		Frames
+//			The total number of frames received, including bad frames, broadcast frames and multicast
+//			frames. (R) (mandatory) (4 bytes)
+//
+//		Broadcast Frames
+//			The total number of received good frames directed to the broadcast address. This does not
+//			include multicast frames. (R) (mandatory) (4 bytes)
+//
+//		Multicast Frames
+//			The total number of received good frames directed to a multicast address. This does not include
+//			broadcast frames. (R) (mandatory) (4 bytes)
+//
+//		Crc Errored Frames
+//			The total number of frames received that had a length (excluding framing bits, but including FCS
+//			octets) of between 64 and 1518 octets, inclusive, but had either a bad FCS with an integral
+//			number of octets (FCS error) or a bad FCS with a non-integral number of octets (alignment
+//			error). (R) (mandatory) (4 bytes)
+//
+//		Undersize Frames
+//			The total number of frames received that were less than 64 octets long but were otherwise well
+//			formed (excluding framing bits, but including FCS octets). (R) (mandatory) (4 bytes)
+//
+//		Oversize Frames
+//			The total number of frames received that were longer than 1518 octets (excluding framing bits,
+//			but including FCS octets) and were otherwise well formed. (R) (mandatory) (4 bytes)
+//
 //		Frames 64 Octets
-//			Frames 64 octets: The total number of received frames (including bad frames) that were 64-octets
-//			long, excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
+//			The total number of received frames (including bad frames) that were 64-octets long, excluding
+//			framing bits but including FCS. (R) (mandatory) (4-bytes)
 //
 //		Frames 65 To 127 Octets
-//			Frames 65 to 127 octets: The total number of received frames (including bad frames) that were
-//			65..127 octets long, excluding framing bits but including FCS. (R) (mandatory) (4 bytes)
+//			The total number of received frames (including bad frames) that were 65..127 octets long,
+//			excluding framing bits but including FCS. (R) (mandatory) (4 bytes)
 //
 //		Frames 128 To 255 Octets
-//			Frames 128 to 255 octets: The total number of frames (including bad frames) received that were
-//			128..255 octets long, excluding framing bits but including FCS. (R) (mandatory) (4 bytes)
+//			The total number of frames (including bad frames) received that were 128..255 octets long,
+//			excluding framing bits but including FCS. (R) (mandatory) (4 bytes)
 //
 //		Frames 256 To 511 Octets
-//			Frames 256 to 511 octets: The total number of frames (including bad frames) received that were
-//			256..511 octets long, excluding framing bits but including FCS. (R) (mandatory) (4 bytes)
+//			The total number of frames (including bad frames) received that were 256..511 octets long,
+//			excluding framing bits but including FCS. (R) (mandatory) (4 bytes)
 //
 //		Frames 512 To 1 023 Octets
 //			Frames 512 to 1-023 octets: The total number of frames (including bad frames) received that were
 //			512..1-023 octets long, excluding framing bits but including FCS. (R) (mandatory) (4 bytes)
 //
 //		Frames 1024 To 1518 Octets
-//			Frames 1024 to 1518 octets: The total number of frames (including bad frames) received that were
-//			1024..1518 octets long, excluding framing bits but including FCS. (R) (mandatory) (4 bytes)
+//			The total number of frames (including bad frames) received that were 1024..1518 octets long,
+//			excluding framing bits but including FCS. (R) (mandatory) (4 bytes)
 //
 type EthernetFrameExtendedPm struct {
 	ManagedEntityDefinition
diff --git a/generated/ethernetframeextendedpm64-bit.go b/generated/ethernetframeextendedpm64-bit.go
index 580319c..4d3eb90 100644
--- a/generated/ethernetframeextendedpm64-bit.go
+++ b/generated/ethernetframeextendedpm64-bit.go
@@ -27,11 +27,11 @@
 
 // EthernetFrameExtendedPm64BitClassID is the 16-bit ID for the OMCI
 // Managed entity Ethernet frame extended PM 64-bit
-const EthernetFrameExtendedPm64BitClassID ClassID = ClassID(425)
+const EthernetFrameExtendedPm64BitClassID = ClassID(425) // 0x01a9
 
 var ethernetframeextendedpm64bitBME *ManagedEntityDefinition
 
-// EthernetFrameExtendedPm64Bit (class ID #425)
+// EthernetFrameExtendedPm64Bit (Class ID: #425 / 0x01a9)
 //	This ME collects some of the PM data at a point where an Ethernet flow can be observed. It is
 //	based on the Etherstats group of [IETF RFC 2819] and [IETF RFC 2863]. Instances of this ME are
 //	created and deleted by the OLT. References to received frames are to be interpreted as the
@@ -39,80 +39,163 @@
 //
 //	For a complete discussion of generic PM architecture, refer to clause I.4.
 //
+//	Relationships
+//		An instance of this ME may be associated with an instance of an ME at any Ethernet interface
+//		within the ONU. The specific ME is identified in the control block attribute.
+//
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. To facilitate
-//			discovery, the identification of instances sequentially starting with 1 is encouraged. (R,
-//			setbycreate) (mandatory) (2 bytes)
+//			This attribute uniquely identifies each instance of this ME. To facilitate discovery, it is
+//			encouraged to identify instances sequentially starting with 1. (R, set-by-create) (mandatory) (2
+//			bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. If
-//			continuous accumulation is enabled in the control block, this attribute is not used and has the
-//			fixed value 0. (R) (mandatory) (1 byte)
+//			This attribute identifies the most recently finished 15-min interval. If continuous accumulation
+//			is enabled in the control block, this attribute is not used and has the fixed value 0. (R)
+//			(mandatory) (1 byte)
 //
 //		Control Block
-//			(R, W, setbycreate) (mandatory) (16 bytes)
+//			This attribute contains fields defined as follows.
+//
+//			Threshold data 64-bit ID: (2 bytes). This attribute points to an instance of the threshold data
+//			64-bit ME that contains PM threshold values. When PM is collected on a continuously running
+//			basis, rather than in 15-min intervals, counter thresholds should not be established. There is
+//			no mechanism to clear a TCA, and any counter parameter may eventually be expected to cross any
+//			given threshold value.
+//
+//			Parent ME class: (2 bytes). This field contains the enumerated value of the ME class of the PM
+//			ME's parent. Together with the parent ME instance field, this permits a given PM ME to be
+//			associated with any OMCI ME. The supported ME classes are as follows.
+//
+//			46	MAC bridge configuration data
+//
+//			47	MAC bridge port configuration data
+//
+//			11	Physical path termination point Ethernet UNI
+//
+//			98	Physical path termination point xDSL UNI part 1
+//
+//			266	GEM IW termination point
+//
+//			281	Multicast GEM IW termination point
+//
+//			329	Virtual Ethernet interface point
+//
+//			162	Physical path termination point MoCA UNI
+//
+//			Parent ME instance: (2 bytes). This field identifies the specific parent ME instance to which
+//			the PM ME is attached.
+//
+//			Accumulation disable: (2 bytes). This bit field allows PM accumulation to be disabled; refer to
+//			Table 9.3.32-1. The default value 0 enables PM collection. If bit 15 is set to 1, no PM is
+//			collected by this ME instance. If bit 15 = 0 and any of bits 14..1 are set to 1, PM collection
+//			is inhibited for the attributes indicated by the 1 bits. Inhibiting PM collection does not
+//			change the value of a PM attribute, but if PM is accumulated in 15-min intervals, the value is
+//			lost at the next 15-min interval boundary.
+//
+//			Bit 16 is an action bit that always reads back as 0. When written to 1, it resets all PM
+//			attributes in the ME, and clears any TCAs that may be outstanding.
+//
+//			TCA disable: (2 bytes). Also clarified in Table 9.3.32-1, this field permits TCAs to be
+//			inhibited, either individually or for the complete ME instance. As with the accumulation disable
+//			field, the default value 0 enables TCAs, and setting the global disable bit overrides the
+//			settings of the individual thresholds. Unlike the accumulation disable field, the bits are
+//			mapped to the thresholds defined in the associated threshold data 1 and 2 ME instances. When the
+//			global or attribute-specific value changes from 0 to 1, outstanding TCAs are cleared, either for
+//			the ME instance globally or for the individual disabled threshold. These bits affect only
+//			notifications, not the underlying parameter accumulation or storage.
+//
+//			If the threshold data 1/2 ID attribute does not contain a valid pointer, this field is not
+//			meaningful.
+//
+//			Thresholds should be used with caution if PM attributes are accumulated continuously.
+//
+//			Control fields: (2 bytes). This field is a bit map whose values govern the behaviour of the PM
+//			ME. Bits are assigned as follows:
+//
+//			Bit 1 (LSB)	The value 1 specifies continuous accumulation, regardless of 15-min intervals. There
+//			is no concept of current and historic accumulators; get and get current data (if supported) both
+//			return current values. The value 0 specifies 15-min accumulators exactly like those of classical
+//			PM.
+//
+//			Bit 2	This bit indicates directionality for the collection of data. The value 0 indicates that
+//			data are to be collected for upstream traffic. The value 1 indicates that data are to be
+//			collected for downstream traffic.
+//
+//			Bits 3..14	Reserved, should be set to 0 by the OLT and ignored by the ONU.
+//
+//			Bit 15	When this bit is 1, the P bits of the TCI field are used to filter the PM data collected.
+//			The value 0 indicates that PM is collected without regard to P bits.
+//
+//			Bit 16	When this bit is 1, the VID bits of the TCI field are used to filter the PM data
+//			collected. The value 0 indicates that PM is collected without regard to VID.
+//
+//			TCI: (2 bytes). This field contains the value optionally used as a filter for the PM data
+//			collected, under the control of bits 15..16 of the control fields. This value is matched to the
+//			outer tag of a frame. Untagged frames are not counted when this field is used.
+//
+//			Reserved: (2 bytes). Not used; should be set to 0 by the OLT and ignored by the ONU.
+//
+//			(R, W, set-by-create) (mandatory) (16 bytes)
 //
 //		Drop Events
-//			Drop events:	The total number of events in which frames were dropped due to a lack of resources.
-//			This is not necessarily the number of frames dropped; it is the number of times this event was
-//			detected. (R) (mandatory) (4 bytes)
+//			The total number of events in which frames were dropped due to lack of resources. This is not
+//			necessarily the number of frames dropped; it is the number of times this event was detected. (R)
+//			(mandatory) (8 bytes)
 //
 //		Octets
-//			Octets:	The total number of octets received, including those in bad frames, excluding framing
-//			bits, but including FCS. (R) (mandatory) (4 bytes)
+//			The total number of octets received, including those in bad frames, excluding framing bits, but
+//			including FCS. (R) (mandatory) (8 bytes)
 //
 //		Frames
-//			Frames:	The total number of frames received, including bad frames, broadcast frames and
-//			multicast frames. (R) (mandatory) (4 bytes)
+//			The total number of frames received, including bad frames, broadcast frames and multicast
+//			frames. (R) (mandatory) (8 bytes)
 //
 //		Broadcast Frames
-//			Broadcast frames: The total number of received good frames directed to the broadcast address.
-//			This does not include multicast frames. (R) (mandatory) (4 bytes)
+//			The total number of received good frames directed to the broadcast address. This does not
+//			include multicast frames. (R) (mandatory) (8 bytes)
 //
 //		Multicast Frames
-//			Multicast frames: The total number of received good frames directed to a multicast address. This
-//			does not include broadcast frames. (R) (mandatory) (4 bytes)
+//			The total number of received good frames directed to a multicast address. This does not include
+//			broadcast frames. (R) (mandatory) (8 bytes)
 //
 //		Crc Errored Frames
-//			CRC errored frames: The total number of frames received that had a length (excluding framing
-//			bits, but including FCS octets) of between 64 and 1518 octets, inclusive, but had either a bad
-//			FCS with an integral number of octets (FCS error) or a bad FCS with a non-integral number of
-//			octets (alignment error). (R) (mandatory) (4 bytes)
+//			The total number of frames received that had a length (excluding framing bits, but including FCS
+//			octets) of between 64 and 1518 octets, inclusive, but had either a bad FCS with an integral
+//			number of octets (FCS error) or a bad FCS with a non-integral number of octets (alignment
+//			error). (R) (mandatory) (8 bytes)
 //
 //		Undersize Frames
-//			Undersize frames: The total number of frames received that were less than 64 octets long but
-//			were otherwise well formed (excluding framing bits, but including FCS octets). (R) (mandatory)
-//			(4 bytes)
+//			The total number of frames received that were less than 64 octets long, but were otherwise well
+//			formed (excluding framing bits, but including FCS octets). (R) (mandatory) (8 bytes)
 //
 //		Oversize Frames
-//			Oversize frames: The total number of frames received that were longer than 1518 octets
-//			(excluding framing bits, but including FCS octets) and were otherwise well formed. (R)
-//			(mandatory) (4 bytes)
+//			The total number of frames received that were longer than 1518 octets (excluding framing bits,
+//			but including FCS octets) and were otherwise well formed. (R) (mandatory) (8 bytes)
 //
 //		Frames 64 Octets
-//			Frames 64 octets: The total number of received frames (including bad frames) that were 64-octets
-//			long, excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
+//			The total number of received frames (including bad frames) that were 64-octets long, excluding
+//			framing bits, but including FCS. (R) (mandatory) (8-bytes)
 //
 //		Frames 65 To 127 Octets
-//			Frames 65 to 127 octets: The total number of received frames (including bad frames) that were
-//			65..127 octets long, excluding framing bits but including FCS. (R) (mandatory) (4 bytes)
+//			The total number of received frames (including bad frames) that were 65..127 octets long,
+//			excluding framing bits but including FCS. (R) (mandatory) (8 bytes)
 //
 //		Frames 128 To 255 Octets
-//			Frames 128 to 255 octets: The total number of frames (including bad frames) received that were
-//			128..255 octets long, excluding framing bits but including FCS. (R) (mandatory) (4 bytes)
+//			The total number of frames (including bad frames) received that were 128..255 octets long,
+//			excluding framing bits but including FCS. (R) (mandatory) (8 bytes)
 //
 //		Frames 256 To 511 Octets
-//			Frames 256 to 511 octets: The total number of frames (including bad frames) received that were
-//			256..511 octets long, excluding framing bits but including FCS. (R) (mandatory) (4 bytes)
+//			The total number of frames (including bad frames) received that were 256..511 octets long,
+//			excluding framing bits but including FCS. (R) (mandatory) (8 bytes)
 //
-//		Frames 512 To 1 023 Octets
-//			Frames 512 to 1-023 octets: The total number of frames (including bad frames) received that were
-//			512..1-023 octets long, excluding framing bits but including FCS. (R) (mandatory) (4 bytes)
+//		Frames 512 To 1023 Octets
+//			The total number of frames (including bad frames) received that were 512..1023 octets long,
+//			excluding framing bits but including FCS. (R) (mandatory) (8 bytes)
 //
 //		Frames 1024 To 1518 Octets
-//			Frames 1024 to 1518 octets: The total number of frames (including bad frames) received that were
-//			1024..1518 octets long, excluding framing bits but including FCS. (R) (mandatory) (4 bytes)
+//			The total number of frames (including bad frames) received that were 1024..1518 octets long,
+//			excluding framing bits but including FCS. (R) (mandatory) (8 bytes)
 //
 type EthernetFrameExtendedPm64Bit struct {
 	ManagedEntityDefinition
diff --git a/generated/ethernetframeperformancemonitoringhistorydatadownstream.go b/generated/ethernetframeperformancemonitoringhistorydatadownstream.go
index bdb2660..de3bb40 100644
--- a/generated/ethernetframeperformancemonitoringhistorydatadownstream.go
+++ b/generated/ethernetframeperformancemonitoringhistorydatadownstream.go
@@ -27,23 +27,22 @@
 
 // EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID is the 16-bit ID for the OMCI
 // Managed entity Ethernet frame performance monitoring history data downstream
-const EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID ClassID = ClassID(321)
+const EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID = ClassID(321) // 0x0141
 
 var ethernetframeperformancemonitoringhistorydatadownstreamBME *ManagedEntityDefinition
 
-// EthernetFramePerformanceMonitoringHistoryDataDownstream (class ID #321)
+// EthernetFramePerformanceMonitoringHistoryDataDownstream (Class ID: #321 / 0x0141)
 //	This ME is identical to the Ethernet frame PM history data upstream ME, with the exception that
 //	it monitors downstream traffic.
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of a MAC bridge port configuration
-//			data. (R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of a MAC bridge port configuration data. (R, setbycreate)
+//			(mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -51,69 +50,66 @@
 //			data 2 ME is optional. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Drop Events
-//			Drop events:	The total number of events in which packets were dropped due to a lack of
-//			resources. This is not necessarily the number of packets dropped; it is the number of times this
-//			event was detected. (R) (mandatory) (4-bytes)
+//			The total number of events in which packets were dropped due to a lack of resources. This is not
+//			necessarily the number of packets dropped; it is the number of times this event was detected.
+//			(R) (mandatory) (4-bytes)
 //
 //		Octets
-//			Octets:	The total number of upstream octets received, including those in bad packets, excluding
-//			framing bits, but including FCS. (R) (mandatory) (4-bytes)
+//			The total number of upstream octets received, including those in bad packets, excluding framing
+//			bits, but including FCS. (R) (mandatory) (4-bytes)
 //
 //		Packets
-//			Packets:	The total number of upstream packets received, including bad packets, broadcast packets
-//			and multicast packets. (R) (mandatory) (4-bytes)
+//			The total number of upstream packets received, including bad packets, broadcast packets and
+//			multicast packets. (R) (mandatory) (4-bytes)
 //
 //		Broadcast Packets
-//			Broadcast packets: The total number of upstream good packets received that were directed to the
-//			broadcast address. This does not include multicast packets. (R) (mandatory) (4-bytes)
+//			The total number of upstream good packets received that were directed to the broadcast address.
+//			This does not include multicast packets. (R) (mandatory) (4-bytes)
 //
 //		Multicast Packets
-//			Multicast packets: The total number of upstream good packets received that were directed to a
-//			multicast address. This does not include broadcast packets. (R) (mandatory) (4-bytes)
+//			The total number of upstream good packets received that were directed to a multicast address.
+//			This does not include broadcast packets. (R) (mandatory) (4-bytes)
 //
 //		Crc Errored Packets
-//			CRC errored packets: The total number of upstream packets received that had a length (excluding
-//			framing bits, but including FCS octets) of between 64-octets and 1518-octets, inclusive, but had
-//			either a bad FCS with an integral number of octets (FCS error) or a bad FCS with a non-integral
-//			number of octets (alignment error). (R) (mandatory) (4-bytes)
+//			The total number of upstream packets received that had a length (excluding framing bits, but
+//			including FCS octets) of between 64-octets and 1518-octets, inclusive, but had either a bad FCS
+//			with an integral number of octets (FCS error) or a bad FCS with a non-integral number of octets
+//			(alignment error). (R) (mandatory) (4-bytes)
 //
 //		Undersize Packets
-//			Undersize packets: The total number of upstream packets received that were less than 64-octets
-//			long, but were otherwise well formed (excluding framing bits, but including FCS). (R)
-//			(mandatory) (4-bytes)
+//			The total number of upstream packets received that were less than 64-octets long, but were
+//			otherwise well formed (excluding framing bits, but including FCS). (R) (mandatory) (4-bytes)
 //
 //		Oversize Packets
 //			NOTE 2 - If 2-000-byte Ethernet frames are supported, counts in this performance parameter are
 //			not necessarily errors.
 //
+//			The total number of upstream packets received that were longer than 1518-octets (excluding
+//			framing bits, but including FCS) and were otherwise well formed. (R) (mandatory) (4-bytes)
+//
 //		Packets 64 Octets
-//			Packets 64 octets: The total number of upstream received packets (including bad packets) that
-//			were 64-octets long, excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
+//			The total number of upstream received packets (including bad packets) that were 64-octets long,
+//			excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
 //
 //		Packets 65 To 127 Octets
-//			Packets 65 to 127 octets: The total number of upstream received packets (including bad packets)
-//			that were 65..127 octets long, excluding framing bits but including FCS. (R) (mandatory)
-//			(4-bytes)
+//			The total number of upstream received packets (including bad packets) that were 65..127 octets
+//			long, excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
 //
 //		Packets 128 To 255 Octets
-//			Packets 128 to 255 octets: The total number of upstream packets (including bad packets) received
-//			that were 128..255 octets long, excluding framing bits but including FCS. (R) (mandatory)
-//			(4-bytes)
+//			The total number of upstream packets (including bad packets) received that were 128..255 octets
+//			long, excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
 //
 //		Packets 256 To 511 Octets
-//			Packets 256 to 511 octets: The total number of upstream packets (including bad packets) received
-//			that were 256..511 octets long, excluding framing bits but including FCS. (R) (mandatory)
-//			(4-bytes)
+//			The total number of upstream packets (including bad packets) received that were 256..511 octets
+//			long, excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
 //
 //		Packets 512 To 1023 Octets
-//			Packets 512 to 1023 octets: The total number of upstream packets (including bad packets)
-//			received that were 512..1-023 octets long, excluding framing bits but including FCS. (R)
-//			(mandatory) (4-bytes)
+//			The total number of upstream packets (including bad packets) received that were 512..1-023
+//			octets long, excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
 //
 //		Packets 1024 To 1518 Octets
-//			Packets 1024 to 1518 octets: The total number of upstream packets (including bad packets)
-//			received that were 1024..1518 octets long, excluding framing bits, but including FCS. (R)
-//			(mandatory) (4-bytes)
+//			The total number of upstream packets (including bad packets) received that were 1024..1518
+//			octets long, excluding framing bits, but including FCS. (R) (mandatory) (4-bytes)
 //
 type EthernetFramePerformanceMonitoringHistoryDataDownstream struct {
 	ManagedEntityDefinition
diff --git a/generated/ethernetframeperformancemonitoringhistorydataupstream.go b/generated/ethernetframeperformancemonitoringhistorydataupstream.go
index c735b43..6970c10 100644
--- a/generated/ethernetframeperformancemonitoringhistorydataupstream.go
+++ b/generated/ethernetframeperformancemonitoringhistorydataupstream.go
@@ -27,11 +27,11 @@
 
 // EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID is the 16-bit ID for the OMCI
 // Managed entity Ethernet frame performance monitoring history data upstream
-const EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID ClassID = ClassID(322)
+const EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID = ClassID(322) // 0x0142
 
 var ethernetframeperformancemonitoringhistorydataupstreamBME *ManagedEntityDefinition
 
-// EthernetFramePerformanceMonitoringHistoryDataUpstream (class ID #322)
+// EthernetFramePerformanceMonitoringHistoryDataUpstream (Class ID: #322 / 0x0142)
 //	This ME collects PM data associated with upstream Ethernet frame delivery. It is based on the
 //	Etherstats group of [IETF RFC 2819]. Instances of this ME are created and deleted by the OLT.
 //
@@ -45,13 +45,12 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of a MAC bridge port configuration
-//			data. (R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of a MAC bridge port configuration data. (R, setbycreate)
+//			(mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -59,69 +58,66 @@
 //			data 2 ME is optional. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Drop Events
-//			Drop events:	The total number of events in which packets were dropped due to a lack of
-//			resources. This is not necessarily the number of packets dropped; it is the number of times this
-//			event was detected. (R) (mandatory) (4-bytes)
+//			The total number of events in which packets were dropped due to a lack of resources. This is not
+//			necessarily the number of packets dropped; it is the number of times this event was detected.
+//			(R) (mandatory) (4-bytes)
 //
 //		Octets
-//			Octets:	The total number of upstream octets received, including those in bad packets, excluding
-//			framing bits, but including FCS. (R) (mandatory) (4-bytes)
+//			The total number of upstream octets received, including those in bad packets, excluding framing
+//			bits, but including FCS. (R) (mandatory) (4-bytes)
 //
 //		Packets
-//			Packets:	The total number of upstream packets received, including bad packets, broadcast packets
-//			and multicast packets. (R) (mandatory) (4-bytes)
+//			The total number of upstream packets received, including bad packets, broadcast packets and
+//			multicast packets. (R) (mandatory) (4-bytes)
 //
 //		Broadcast Packets
-//			Broadcast packets: The total number of upstream good packets received that were directed to the
-//			broadcast address. This does not include multicast packets. (R) (mandatory) (4-bytes)
+//			The total number of upstream good packets received that were directed to the broadcast address.
+//			This does not include multicast packets. (R) (mandatory) (4-bytes)
 //
 //		Multicast Packets
-//			Multicast packets: The total number of upstream good packets received that were directed to a
-//			multicast address. This does not include broadcast packets. (R) (mandatory) (4-bytes)
+//			The total number of upstream good packets received that were directed to a multicast address.
+//			This does not include broadcast packets. (R) (mandatory) (4-bytes)
 //
 //		Crc Errored Packets
-//			CRC errored packets: The total number of upstream packets received that had a length (excluding
-//			framing bits, but including FCS octets) of between 64-octets and 1518-octets, inclusive, but had
-//			either a bad FCS with an integral number of octets (FCS error) or a bad FCS with a non-integral
-//			number of octets (alignment error). (R) (mandatory) (4-bytes)
+//			The total number of upstream packets received that had a length (excluding framing bits, but
+//			including FCS octets) of between 64-octets and 1518-octets, inclusive, but had either a bad FCS
+//			with an integral number of octets (FCS error) or a bad FCS with a non-integral number of octets
+//			(alignment error). (R) (mandatory) (4-bytes)
 //
 //		Undersize Packets
-//			Undersize packets: The total number of upstream packets received that were less than 64-octets
-//			long, but were otherwise well formed (excluding framing bits, but including FCS). (R)
-//			(mandatory) (4-bytes)
+//			The total number of upstream packets received that were less than 64-octets long, but were
+//			otherwise well formed (excluding framing bits, but including FCS). (R) (mandatory) (4-bytes)
 //
 //		Oversize Packets
 //			NOTE 2 - If 2-000-byte Ethernet frames are supported, counts in this performance parameter are
 //			not necessarily errors.
 //
+//			The total number of upstream packets received that were longer than 1518-octets (excluding
+//			framing bits, but including FCS) and were otherwise well formed. (R) (mandatory) (4-bytes)
+//
 //		Packets 64 Octets
-//			Packets 64 octets: The total number of upstream received packets (including bad packets) that
-//			were 64-octets long, excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
+//			The total number of upstream received packets (including bad packets) that were 64-octets long,
+//			excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
 //
 //		Packets 65 To 127 Octets
-//			Packets 65 to 127 octets: The total number of upstream received packets (including bad packets)
-//			that were 65..127 octets long, excluding framing bits but including FCS. (R) (mandatory)
-//			(4-bytes)
+//			The total number of upstream received packets (including bad packets) that were 65..127 octets
+//			long, excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
 //
 //		Packets 128 To 255 Octets
-//			Packets 128 to 255 octets: The total number of upstream packets (including bad packets) received
-//			that were 128..255 octets long, excluding framing bits but including FCS. (R) (mandatory)
-//			(4-bytes)
+//			The total number of upstream packets (including bad packets) received that were 128..255 octets
+//			long, excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
 //
 //		Packets 256 To 511 Octets
-//			Packets 256 to 511 octets: The total number of upstream packets (including bad packets) received
-//			that were 256..511 octets long, excluding framing bits but including FCS. (R) (mandatory)
-//			(4-bytes)
+//			The total number of upstream packets (including bad packets) received that were 256..511 octets
+//			long, excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
 //
 //		Packets 512 To 1023 Octets
-//			Packets 512 to 1023 octets: The total number of upstream packets (including bad packets)
-//			received that were 512..1-023 octets long, excluding framing bits but including FCS. (R)
-//			(mandatory) (4-bytes)
+//			The total number of upstream packets (including bad packets) received that were 512..1-023
+//			octets long, excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
 //
 //		Packets 1024 To 1518 Octets
-//			Packets 1024 to 1518 octets: The total number of upstream packets (including bad packets)
-//			received that were 1024..1518 octets long, excluding framing bits, but including FCS. (R)
-//			(mandatory) (4-bytes)
+//			The total number of upstream packets (including bad packets) received that were 1024..1518
+//			octets long, excluding framing bits, but including FCS. (R) (mandatory) (4-bytes)
 //
 type EthernetFramePerformanceMonitoringHistoryDataUpstream struct {
 	ManagedEntityDefinition
diff --git a/generated/ethernetperformancemonitoringhistorydata.go b/generated/ethernetperformancemonitoringhistorydata.go
index 13174a7..37e2876 100644
--- a/generated/ethernetperformancemonitoringhistorydata.go
+++ b/generated/ethernetperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // EthernetPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity Ethernet performance monitoring history data
-const EthernetPerformanceMonitoringHistoryDataClassID ClassID = ClassID(24)
+const EthernetPerformanceMonitoringHistoryDataClassID = ClassID(24) // 0x0018
 
 var ethernetperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// EthernetPerformanceMonitoringHistoryData (class ID #24)
+// EthernetPerformanceMonitoringHistoryData (Class ID: #24 / 0x0018)
 //	This ME collects some of the PM data for a physical Ethernet interface. Instances of this ME are
 //	created and deleted by the OLT.
 //
@@ -42,78 +42,76 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP Ethernet UNI. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP Ethernet UNI. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 and 2 MEs
 //			that contains PM threshold values. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Fcs Errors
-//			FCS errors:	This attribute counts frames received on a particular interface that were an
-//			integral number of octets in length but failed the FCS check. The count is incremented when the
-//			MAC service returns the frameCheckError status to the link layer control (LLC) or other MAC
-//			user. Received frames for which multiple error conditions are obtained are counted according to
-//			the error status presented to the LLC. (R) (mandatory) (4-bytes)
+//			This attribute counts frames received on a particular interface that were an integral number of
+//			octets in length but failed the FCS check. The count is incremented when the MAC service returns
+//			the frameCheckError status to the link layer control (LLC) or other MAC user. Received frames
+//			for which multiple error conditions are obtained are counted according to the error status
+//			presented to the LLC. (R) (mandatory) (4-bytes)
 //
 //		Excessive Collision Counter
-//			Excessive collision counter: This attribute counts frames whose transmission failed due to
-//			excessive collisions.-(R) (mandatory) (4-bytes)
+//			This attribute counts frames whose transmission failed due to excessive collisions.-(R)
+//			(mandatory) (4-bytes)
 //
 //		Late Collision Counter
-//			Late collision counter: This attribute counts the number of times that a collision was detected
-//			later than 512 bit times into the transmission of a packet. (R) (mandatory) (4-bytes)
+//			This attribute counts the number of times that a collision was detected later than 512 bit times
+//			into the transmission of a packet. (R) (mandatory) (4-bytes)
 //
 //		Frames Too Long
-//			Frames too long: This attribute counts received frames that exceeded the maximum permitted frame
-//			size. The count is incremented when the MAC service returns the frameTooLong status to the LLC.
-//			(R) (mandatory) (4-bytes)
+//			This attribute counts received frames that exceeded the maximum permitted frame size. The count
+//			is incremented when the MAC service returns the frameTooLong status to the LLC. (R) (mandatory)
+//			(4-bytes)
 //
 //		Buffer Overflows On Receive
-//			Buffer overflows on receive: This attribute counts the number of times that the receive buffer
-//			overflowed. (R) (mandatory) (4-bytes)
+//			This attribute counts the number of times that the receive buffer overflowed. (R) (mandatory)
+//			(4-bytes)
 //
 //		Buffer Overflows On Transmit
-//			Buffer overflows on transmit: This attribute counts the number of times that the transmit buffer
-//			overflowed. (R) (mandatory) (4-bytes)
+//			This attribute counts the number of times that the transmit buffer overflowed. (R) (mandatory)
+//			(4-bytes)
 //
 //		Single Collision Frame Counter
-//			Single collision frame counter: This attribute counts successfully transmitted frames whose
-//			transmission was delayed by exactly one collision. (R) (mandatory) (4-bytes)
+//			This attribute counts successfully transmitted frames whose transmission was delayed by exactly
+//			one collision. (R) (mandatory) (4-bytes)
 //
 //		Multiple Collisions Frame Counter
-//			Multiple collisions frame counter: This attribute counts successfully transmitted frames whose
-//			transmission was delayed by more than one collision. (R) (mandatory) (4-bytes)
+//			This attribute counts successfully transmitted frames whose transmission was delayed by more
+//			than one collision. (R) (mandatory) (4-bytes)
 //
 //		Sqe Counter
-//			SQE counter: This attribute counts the number of times that the SQE test error message was
-//			generated by the PLS sublayer. (R) (mandatory) (4-bytes)
+//			This attribute counts the number of times that the SQE test error message was generated by the
+//			PLS sublayer. (R) (mandatory) (4-bytes)
 //
 //		Deferred Transmission Counter
-//			Deferred transmission counter: This attribute counts frames whose first transmission attempt was
-//			delayed because the medium was busy. The count does not include frames involved in collisions.
-//			(R) (mandatory) (4-bytes)
+//			This attribute counts frames whose first transmission attempt was delayed because the medium was
+//			busy. The count does not include frames involved in collisions. (R) (mandatory) (4-bytes)
 //
 //		Internal Mac Transmit Error Counter
-//			Internal MAC transmit error counter: This attribute counts frames whose transmission failed due
-//			to an internal MAC sublayer transmit error. (R) (mandatory) (4-bytes)
+//			This attribute counts frames whose transmission failed due to an internal MAC sublayer transmit
+//			error. (R) (mandatory) (4-bytes)
 //
 //		Carrier Sense Error Counter
-//			Carrier sense error counter: This attribute counts the number of times that carrier sense was
-//			lost or never asserted when attempting to transmit a frame. (R) (mandatory) (4-bytes)
+//			This attribute counts the number of times that carrier sense was lost or never asserted when
+//			attempting to transmit a frame. (R) (mandatory) (4-bytes)
 //
 //		Alignment Error Counter
-//			Alignment error counter: This attribute counts received frames that were not an integral number
-//			of octets in length and did not pass the FCS check. (R) (mandatory) (4-bytes)
+//			This attribute counts received frames that were not an integral number of octets in length and
+//			did not pass the FCS check. (R) (mandatory) (4-bytes)
 //
 //		Internal Mac Receive Error Counter
-//			Internal MAC receive error counter: This attribute counts frames whose reception failed due to
-//			an internal MAC sublayer receive error. (R) (mandatory) (4-bytes)
+//			This attribute counts frames whose reception failed due to an internal MAC sublayer receive
+//			error. (R) (mandatory) (4-bytes)
 //
 type EthernetPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/ethernetperformancemonitoringhistorydata2.go b/generated/ethernetperformancemonitoringhistorydata2.go
index 251eac4..6bb6fa1 100644
--- a/generated/ethernetperformancemonitoringhistorydata2.go
+++ b/generated/ethernetperformancemonitoringhistorydata2.go
@@ -27,11 +27,11 @@
 
 // EthernetPerformanceMonitoringHistoryData2ClassID is the 16-bit ID for the OMCI
 // Managed entity Ethernet performance monitoring history data 2
-const EthernetPerformanceMonitoringHistoryData2ClassID ClassID = ClassID(89)
+const EthernetPerformanceMonitoringHistoryData2ClassID = ClassID(89) // 0x0059
 
 var ethernetperformancemonitoringhistorydata2BME *ManagedEntityDefinition
 
-// EthernetPerformanceMonitoringHistoryData2 (class ID #89)
+// EthernetPerformanceMonitoringHistoryData2 (Class ID: #89 / 0x0059)
 //	This ME collects additional PM data for a physical Ethernet interface. Instances of this ME are
 //	created and deleted by the OLT.
 //
@@ -43,13 +43,12 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP Ethernet UNI. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP Ethernet UNI. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -57,8 +56,8 @@
 //			data 2 ME is optional. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Pppoe Filtered Frame Counter
-//			PPPoE filtered frame counter: This attribute counts the number of frames discarded due to PPPoE
-//			filtering. (R) (mandatory) (4-bytes)
+//			This attribute counts the number of frames discarded due to PPPoE filtering. (R) (mandatory)
+//			(4-bytes)
 //
 type EthernetPerformanceMonitoringHistoryData2 struct {
 	ManagedEntityDefinition
diff --git a/generated/ethernetperformancemonitoringhistorydata3.go b/generated/ethernetperformancemonitoringhistorydata3.go
index f8f5772..8149d84 100644
--- a/generated/ethernetperformancemonitoringhistorydata3.go
+++ b/generated/ethernetperformancemonitoringhistorydata3.go
@@ -27,11 +27,11 @@
 
 // EthernetPerformanceMonitoringHistoryData3ClassID is the 16-bit ID for the OMCI
 // Managed entity Ethernet performance monitoring history data 3
-const EthernetPerformanceMonitoringHistoryData3ClassID ClassID = ClassID(296)
+const EthernetPerformanceMonitoringHistoryData3ClassID = ClassID(296) // 0x0128
 
 var ethernetperformancemonitoringhistorydata3BME *ManagedEntityDefinition
 
-// EthernetPerformanceMonitoringHistoryData3 (class ID #296)
+// EthernetPerformanceMonitoringHistoryData3 (Class ID: #296 / 0x0128)
 //	This ME collects PM data associated with an Ethernet interface. It includes parameters defined
 //	in the Ethernet statistics group of [IETF RFC 2819] that are not already covered by previously
 //	defined Ethernet monitoring MEs. The received direction is from the CPE towards the network
@@ -54,13 +54,12 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP Ethernet UNI. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP Ethernet UNI. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -68,67 +67,66 @@
 //			data 2 ME is optional. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Drop Events
-//			Drop events:	The total number of events in which packets were dropped due to a lack of
-//			resources. This is not necessarily the number of packets dropped; it is the number of times this
-//			event was detected. (R) (mandatory) (4-bytes)
+//			The total number of events in which packets were dropped due to a lack of resources. This is not
+//			necessarily the number of packets dropped; it is the number of times this event was detected.
+//			(R) (mandatory) (4-bytes)
 //
 //		Octets
-//			Octets:	The total number of octets received from the CPE, including those in bad packets,
-//			excluding framing bytes, but including FCS. (R) (mandatory) (4-bytes)
+//			The total number of octets received from the CPE, including those in bad packets, excluding
+//			framing bytes, but including FCS. (R) (mandatory) (4-bytes)
 //
 //		Packets
-//			Packets:	The total number of packets received, including bad packets, broadcast packets and
-//			multicast packets. (R) (mandatory) (4-bytes)
+//			The total number of packets received, including bad packets, broadcast packets and multicast
+//			packets. (R) (mandatory) (4-bytes)
 //
 //		Broadcast Packets
-//			Broadcast packets: The total number of received good packets directed to the broadcast address.
-//			This does not include multicast packets. (R) (mandatory) (4-bytes)
+//			The total number of received good packets directed to the broadcast address. This does not
+//			include multicast packets. (R) (mandatory) (4-bytes)
 //
 //		Multicast Packets
-//			Multicast packets: The total number of received good packets directed to a multicast address.
-//			This does not include broadcast packets. (R) (mandatory) (4-bytes)
+//			The total number of received good packets directed to a multicast address. This does not include
+//			broadcast packets. (R) (mandatory) (4-bytes)
 //
 //		Undersize Packets
-//			Undersize packets: The total number of packets received that were less than 64 octets long, but
-//			were otherwise well formed (excluding framing bits, but including FCS). (R) (mandatory)
-//			(4-bytes)
+//			The total number of packets received that were less than 64 octets long, but were otherwise well
+//			formed (excluding framing bits, but including FCS). (R) (mandatory) (4-bytes)
 //
 //		Fragments
-//			Fragments:	The total number of packets received that were less than 64 octets long, excluding
-//			framing bits but including FCS octets, and had either a bad FCS with an integral number of
-//			octets (FCS error) or a bad FCS with a non-integral number of octets (alignment error). It is
-//			entirely normal for this attribute to increment. This is because it counts both runts (which are
-//			normal occurrences due to collisions) and noise hits. (R) (mandatory) (4-bytes)
+//			The total number of packets received that were less than 64 octets long, excluding framing bits
+//			but including FCS octets, and had either a bad FCS with an integral number of octets (FCS error)
+//			or a bad FCS with a non-integral number of octets (alignment error). It is entirely normal for
+//			this attribute to increment. This is because it counts both runts (which are normal occurrences
+//			due to collisions) and noise hits. (R) (mandatory) (4-bytes)
 //
 //		Jabbers
-//			Jabbers:	The total number of packets received that were longer than 1518 octets, excluding
-//			framing bits but including FCS octets, and had either a bad FCS with an integral number of
-//			octets (FCS error) or a bad FCS with a non-integral number of octets (alignment error). The
-//			range to detect jabber is between 20 ms and 150 ms. (R) (mandatory) (4-bytes)
+//			The total number of packets received that were longer than 1518 octets, excluding framing bits
+//			but including FCS octets, and had either a bad FCS with an integral number of octets (FCS error)
+//			or a bad FCS with a non-integral number of octets (alignment error). The range to detect jabber
+//			is between 20 ms and 150 ms. (R) (mandatory) (4-bytes)
 //
 //		Packets 64 Octets
-//			Packets 64 octets: The total number of received packets (including bad packets) that were
-//			64-octets long, excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
+//			The total number of received packets (including bad packets) that were 64-octets long, excluding
+//			framing bits but including FCS. (R) (mandatory) (4-bytes)
 //
 //		Packets 65 To 127 Octets
-//			Packets 65 to 127 octets: The total number of received packets (including bad packets) that were
-//			65..127 octets long, excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
+//			The total number of received packets (including bad packets) that were 65..127 octets long,
+//			excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
 //
 //		Packets 128 To 255 Octets
-//			Packets 128 to 255 octets: The total number of packets (including bad packets) received that
-//			were 128..255 octets long, excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
+//			The total number of packets (including bad packets) received that were 128..255 octets long,
+//			excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
 //
 //		Packets 256 To 511 Octets
-//			Packets 256 to 511 octets: The total number of packets (including bad packets) received that
-//			were 256..511 octets long, excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
+//			The total number of packets (including bad packets) received that were 256..511 octets long,
+//			excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
 //
 //		Packets 512 To 1023 Octets
-//			Packets 512 to 1023 octets: The total number of packets (including bad packets) received that
-//			were 512..1023 octets long, excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
+//			The total number of packets (including bad packets) received that were 512..1023 octets long,
+//			excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
 //
 //		Packets 1024 To 1518 Octets
-//			Packets 1024 to 1518 octets: The total number of packets (including bad packets) received that
-//			were 1024..1518 octets long, excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
+//			The total number of packets (including bad packets) received that were 1024..1518 octets long,
+//			excluding framing bits but including FCS. (R) (mandatory) (4-bytes)
 //
 type EthernetPerformanceMonitoringHistoryData3 struct {
 	ManagedEntityDefinition
diff --git a/generated/ethernetpseudowireparameters.go b/generated/ethernetpseudowireparameters.go
index d49565f..cd64e28 100644
--- a/generated/ethernetpseudowireparameters.go
+++ b/generated/ethernetpseudowireparameters.go
@@ -27,11 +27,11 @@
 
 // EthernetPseudowireParametersClassID is the 16-bit ID for the OMCI
 // Managed entity Ethernet pseudowire parameters
-const EthernetPseudowireParametersClassID ClassID = ClassID(400)
+const EthernetPseudowireParametersClassID = ClassID(400) // 0x0190
 
 var ethernetpseudowireparametersBME *ManagedEntityDefinition
 
-// EthernetPseudowireParameters (class ID #400)
+// EthernetPseudowireParameters (Class ID: #400 / 0x0190)
 //	This ME contains the Ethernet pseudowire parameters. Instances of this ME are created and
 //	deleted by the OLT.
 //
@@ -40,14 +40,14 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID:	This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PW Ethernet configuration data
-//			ME. (R, set-by-create) (mandatory) (2 bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PW Ethernet configuration data ME. (R, set-by-create)
+//			(mandatory) (2 bytes)
 //
 //		Mtu
-//			MTU:	This attribute identifies the maximum transmission unit (bytes) that can be received from
-//			the CPE in the upstream direction. Larger frames are discarded. (R, W, set-by-create)
-//			(mandatory) (2 bytes)
+//			This attribute identifies the maximum transmission unit (bytes) that can be received from the
+//			CPE in the upstream direction. Larger frames are discarded. (R, W, set-by-create) (mandatory) (2
+//			bytes)
 //
 type EthernetPseudowireParameters struct {
 	ManagedEntityDefinition
diff --git a/generated/extendedvlantaggingoperationconfigurationdata.go b/generated/extendedvlantaggingoperationconfigurationdata.go
index 57ba11d..0487c71 100644
--- a/generated/extendedvlantaggingoperationconfigurationdata.go
+++ b/generated/extendedvlantaggingoperationconfigurationdata.go
@@ -27,14 +27,19 @@
 
 // ExtendedVlanTaggingOperationConfigurationDataClassID is the 16-bit ID for the OMCI
 // Managed entity Extended VLAN tagging operation configuration data
-const ExtendedVlanTaggingOperationConfigurationDataClassID ClassID = ClassID(171)
+const ExtendedVlanTaggingOperationConfigurationDataClassID = ClassID(171) // 0x00ab
 
 var extendedvlantaggingoperationconfigurationdataBME *ManagedEntityDefinition
 
-// ExtendedVlanTaggingOperationConfigurationData (class ID #171)
-//	This ME organizes data associated with VLAN tagging. Regardless of its point of attachment, the
-//	specified tagging operations refer to the upstream direction. Instances of this ME are created
-//	and deleted by the OLT.
+// ExtendedVlanTaggingOperationConfigurationData (Class ID: #171 / 0x00ab)
+//	This ME organizes data associated with VLAN classification and tagging operations. Regardless of
+//	its point of attachment, the specified tagging operations refer to the upstream direction.
+//	Instances of this ME are created and deleted by the OLT.
+//
+//	Through separate attributes, this ME supports either a Received frame VLAN tagging operation
+//	table attribute in its backward compatible form, or an enhanced frame classification and
+//	processing capability. The OLT can determine whether the ONU supports the enhanced capability
+//	through the Enhanced mode attribute of the ONU3-G ME.
 //
 //	Relationships
 //		Zero or one instance of this ME may exist for an instance of any ME that can terminate or modify
@@ -49,10 +54,45 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute provides a unique number for each instance of this ME. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute provides a unique number for each instance of this ME. (R, setbycreate)
+//			(mandatory) (2-bytes)
 //
 //		Association Type
+//			This attribute identifies the type of the ME associated with this extended VLAN tagging ME.
+//			Values are assigned as follows.
+//
+//			0	MAC bridge port configuration data
+//
+//			1	IEEE 802.1p mapper service profile
+//
+//			2	Physical path termination point Ethernet UNI
+//
+//			3	IP host config data or IPv6 host config data
+//
+//			4	Physical path termination point xDSL UNI
+//
+//			5	GEM IW termination point
+//
+//			6	Multicast GEM IW termination point
+//
+//			7	Physical path termination point MoCA UNI
+//
+//			8	Reserved
+//
+//			9	Ethernet flow termination point
+//
+//			10	Virtual Ethernet interface point
+//
+//			11	MPLS pseudowire termination point
+//
+//			12	EFM bonding group
+//
+//			(R,-W, setbycreate) (mandatory) (1-byte)
+//
+//			NOTE 1 - If a MAC bridge is configured, code points 1, 5, 6 and 11 are associated with the ANI
+//			side of the MAC bridge. Code point 0 is associated with the ANI or UNI side, depending on the
+//			location of the MAC bridge port. The other code points are associated with the UNI side.
+//
 //			When the extended VLAN tagging ME is associated with the ANI side, it behaves as an upstream
 //			egress rule, and as a downstream ingress rule when the downstream mode attribute is equal to 0.
 //			When the extended VLAN tagging ME is associated with the UNI side, the extended VLAN tagging ME
@@ -60,35 +100,455 @@
 //			attribute is equal to 0.
 //
 //		Received Frame Vlan Tagging Operation Table Max Size
-//			Received frame VLAN tagging operation table max size: This attribute indicates the maximum
-//			number of entries that can be set in the received frame VLAN tagging operation table. (R)
-//			(mandatory) (2-bytes)
+//			This attribute indicates the maximum number of entries that can be set in the received frame
+//			VLAN tagging operation table. (R) (mandatory) (2-bytes)
 //
 //		Input Tpid
-//			Input TPID:	This attribute gives the special TPID value for operations on the input (filtering)
-//			side of the table. Typical values include 0x88A8 and 0x9100. (R,-W) (mandatory) (2-bytes)
+//			This attribute gives the special TPID value for operations on the input (filtering) side of the
+//			table. Typical values include 0x88A8 and 0x9100. (R,-W) (mandatory) (2-bytes)
 //
 //		Output Tpid
-//			Output TPID: This attribute gives the special TPID value for operations on the output (tagging)
-//			side of the table. Typical values include 0x88A8 and 0x9100. (R,-W) (mandatory) (2-bytes)
+//			This attribute gives the special TPID value for operations on the output (tagging) side of the
+//			table. Typical values include 0x88A8 and 0x9100. (R,-W) (mandatory) (2-bytes)
 //
 //		Downstream Mode
+//			Regardless of its association, the rules of the received frame VLAN tagging operation table
+//			attribute pertain to upstream traffic. The downstream mode attribute defines the tagging action
+//			to be applied to downstream frames.
+//
+//			The received frame VLAN tagging operation table installs defaults upstream rules. In the
+//			downstream direction, the upstream default rules with the default treatment do not apply. It
+//			should be noted that downstream frame treatment is defined by the downstream mode attribute and
+//			is not affected by the upstream default rules.
+//
+//			The received frame VLAN tagging operation table can result in two types of rule mappings:
+//
+//			o	One to one mapping: A table contains one or more rules that result in unique mappings between
+//			the ingress and egress flows.
+//
+//			o	Many to one mapping: A table contains more than one rule that results in the same ANI-side tag
+//			configuration.
+//
+//			For one-to-one  mappings, the inverse operation to apply in the downstream direction (in the
+//			case of bidirectional flows) is the inverse operation of the upstream rule.
+//
+//			Many-to-one mappings are possible however, and these are treated as follows.
+//
+//			o	If an upstream many-to-one mapping results from multiple operation rules producing the same
+//			ANI-side tag configuration, then the first matching rule in the list defines the inverse
+//			operation. The meaning of match depends on the value of the downstream mode attribute.
+//
+//			o	If the many-to-one mapping results from "don't care" fields in the filter being replaced with
+//			provisioned fields in the ANI side tags, then the inverse is defined to set the corresponding
+//			fields on the ANI side to their lowest legal value.
+//
+//			If the upstream rule merely copies (i.e., no explicit value is specified in the filter field) an
+//			inbound tag value to an outbound tag value, the comparison in the downstream direction applies
+//			to all tag values. This applies separately to the VID and P-bit fields. For example, with a
+//			downstream mode of 2 and an upstream rule that translates the VID while carrying forward the
+//			P-bit value, downstream frames that match the specified WAN-side VID will match any P-bit value
+//			and will translate the VID.
+//
+//			0	The operation performed in the downstream direction is the inverse of that performed in the
+//			upstream direction. Which treatment and filter fields are used for downstream filtering and the
+//			handling of unmatched frames are left to the implementation of the ONU.
+//
+//			1	Regardless of the filter rules, no operation is performed in the downstream direction. All
+//			downstream frames are forwarded unmodified.
+//
+//			2	Filter on VID and P-bit value. On a match, perform the inverse operation on both the VID and
+//			P-bit value. If no match is found, forward the frame unmodified.
+//
+//			3	Filter on VID only. On a match, perform the inverse VID operation only; pass the P bits
+//			through. If no match is found, forward the frame unmodified.
+//
+//			4	Filter on P-bit only. On a match, perform the inverse P-bit operation only; pass the VID
+//			through. If no match is found, forward the frame unmodified.
+//
+//			5	Filter on VID and P-bit value. On a match, perform the inverse operation on both the VID and
+//			P-bit value. If no match is found, discard the frame.
+//
+//			6	Filter on VID. On a match, perform the inverse operation on the VID only; pass the P bits
+//			through. If no match is found, discard the frame.
+//
+//			7	Filter on P-bit only. On a match, perform the inverse P-bit operation only; pass the VID
+//			through. If no match is found, discard the frame.
+//
+//			8	Regardless of the filter rules, discard all downstream traffic.
+//
+//			Please refer to Table 9.3.13-2 for example downstream mode use cases.
+//
 //			All other values are reserved. (R, W) (mandatory) (1 byte)
 //
 //		Received Frame Vlan Tagging Operation Table
-//			111	Set TPID-=-output TPID, DEI = 1
+//			Padding: (8 bits)
+//
+//			Filter Ethertype: (4 bits) the Ethertype value on which to filter received frames, as follows.
+//
+//			NOTE 3 - This filter is recommended for use on untagged frames or frames with priority tags
+//			only.
+//
+//			0	Do not filter on Ethertype.
+//
+//			1	Ethertype = 0x0800 (filter IPoE frames)
+//
+//			2	Ethertype = 0x8863 or 0x8864 (filter PPPoE frames)
+//
+//			3	Ethertype = 0x0806 (filter ARP frames)
+//
+//			4	Ethertype = 0x86DD (filter IPv6 IpoE frames)
+//
+//			5	Ethertype = 0x888E (filter EAPOL frames)
+//
+//			Other values: reserved.
+//
+//			Filter on extended criteria: (8 bits) filter on key upper level protocols:
+//
+//			0	Do not filter on extended criteria
+//
+//			1	DHCPv4 - frames matching the well-known DHCPv4 UDP ports (67, 68) will be filtered by this
+//			criteria code point.
+//
+//			2	DHCPv6 - frames matching the well-known DHCPv6 UDP ports (546, 547) will be filtered by this
+//			criteria code point.
+//
+//			NOTE 4 - This filter is recommended for use on untagged frames or priority framed tags only.
+//
+//			Treatment tags to remove: (2 bits) Defines the tag treatment. The following values are
+//			supported:
+//
+//			0..2	Remove 0, 1 or 2 tags, respectively. If one tag is specified, then the outer tag is
+//			stripped from double-tagged frames.
+//
+//			3	Discard the frame. No symmetric downstream operation exists; i.e., this rule is ignored in the
+//			downstream direction.
+//
+//			Padding: (10 bits)
+//
+//			Treatment outer priority: (4 bits): Defines the outer VLAN priority treatment. The following
+//			values are supported:
+//
+//			0..7	Add an outer tag, and insert this value as the priority in the outer VLAN tag.
+//
+//			8	Add an outer tag, and copy the outer priority from the inner priority of the received frame.
+//
+//			9	Add an outer tag, and copy the outer priority from the outer priority of the received frame.
+//
+//			10	Add an outer tag, and derive P bits from the DSCP field of the incoming frame according to
+//			the Extended VLAN tagging operation configuration data ME DSCP to P-bit mapping attribute.
+//
+//			15	Do not add an outer tag.
+//
+//			Other values: reserved.
+//
+//			Treatment outer VID: (13 bits). Defines the outer VID treatment. The following values are
+//			supported:
+//
+//			0..4094	Use this value as the VID in the outer VLAN tag.
+//
+//			4096	Copy the outer VID from the inner VID of the received frame.
+//
+//			4097	Copy the outer VID from the outer VID of the received frame.
+//
+//			Other values: reserved.
+//
+//			Treatment outer TPID/DEI: (3 bits). Defines the outer VLAN TPID/DEI treatment. The following
+//			values are supported:
+//
+//			000	Copy TPID (and DEI, if present) from the inner tag of the received frame.
+//
+//			001	Copy TPID (and DEI, if present) from the outer tag of the received frame.
+//
+//			010	Set TPID = output TPID attribute value of the Extended VLAN tagging operation configuration
+//			data ME and copy DEI bit from the inner tag of the received frame
+//
+//			011	Set TPID = output TPID attribute value of the Extended VLAN tagging operation configuration
+//			data ME and copy DEI from the outer tag of the received frame
+//
+//			100	Set TPID = 0x8100
+//
+//			101	Reserved
+//
+//			110	Set TPID = output TPID attribute value of the Extended VLAN tagging operation configuration
+//			data ME and set DEI = 0
+//
+//			111	Set TPID = output TPID attribute value of the Extended VLAN tagging operation configuration
+//			data ME and set DEI = 1
+//
+//			Padding: (12 bits)
+//
+//			Treatment inner priority: (4 bits). Defines the inner VLAN priority treatment. The following
+//			values are supported:
+//
+//			0..7	Add an inner tag, and insert this value as the priority to insert in the inner VLAN tag.
+//
+//			8	Add an inner tag, and copy the inner priority from the inner priority of the received frame.
+//
+//			9	Add an inner tag, and copy the inner priority from the outer priority of the received frame.
+//
+//			10	Add an inner tag, and derive P bits from the DSCP field of the incoming frame according to
+//			the Extended VLAN tagging operation configuration data ME DSCP to P-bit mapping attribute.
+//
+//			15	Do not add an inner tag.
+//
+//			Other values: reserved.
+//
+//			Treatment inner VID: (13 bits): Defines the inner VLAN VID treatment.  The following values are
+//			supported:
+//
+//			0..4094	Use this value as the VID in the inner VLAN tag.
+//
+//			4096	Copy the inner VID from the inner VID of the received frame.
+//
+//			4097	Copy the inner VID from the outer VID of the received frame.
+//
+//			Other values: reserved.
+//
+//			Treatment inner TPID/DEI: (3 bits). Defines the inner VLAN TPID/DEI treatment. The following
+//			values are supported:
+//
+//			000	Copy TPID (and DEI, if present) from the inner tag of the received frame.
+//
+//			001	Copy TPID (and DEI, if present) from the outer tag of the received frame.
+//
+//			010	Set TPID = output TPID attribute value of the Extended VLAN tagging operation configuration
+//			data ME and copy the DEI bit from the inner tag of the received frame.
+//
+//			011	Set TPID = output TPID attribute value of the Extended VLAN tagging operation configuration
+//			data ME and, copy the DEI from the outer tag of the received frame.
+//
+//			100	Set TPID = 0x8100
+//
+//			101	Reserved
+//
+//			110	Set TPID = output TPID attribute value of the Extended VLAN tagging operation configuration
+//			data ME and set DEI = 0
+//
+//			111	Set TPID = output TPID attribute value of the Extended VLAN tagging operation configuration
+//			data ME and set DEI = 1
+//
+//			This attribute is a table that filters and tags upstream frames. Each entry represents a tagging
+//			rule, comprising a filtering part (the first eight fields) and a treatment part (the last seven
+//			fields). Each incoming upstream packet is matched against each rule in list order. The first
+//			rule that matches the packet is selected as the active rule, and the packet is then treated
+//			according to that rule.
+//
+//			There are three categories of rules: zero-tag, single-tag, and double-tag rules. Logically,
+//			these categories are separate, and apply to their respective incoming frame types. In other
+//			words, a single-tag rule should not apply to a double-tagged frame, even though the single-tag
+//			rule might match the outer tag of the double-tagged frame.
+//
+//			Single-tag rules have a filter outer priority field-= 15 (indicating no external tag), zero-tag
+//			rules have both filter priority fields-= 15 (indicating no tags), and double-tag rules have both
+//			filter priority fields set to a value that differs from 15 (indicating two tags).
+//
+//			Each tagging rule is based on a remove or an add operation, where up to two tags can be removed
+//			or added. A modify operation is applied by the combination of remove and add.
+//
+//			By convention, when a single tag is added, the treatments use the inner tag data fields. This is
+//			true even for treatments where a single tag is added to a frame that already has a tag, i.e.,
+//			added as a second tag. The outer tag data fields are used only when two tags are added by the
+//			same rule.
+//
+//			The terms inner and outer only have meaning with respect to the tags that are being filtered or
+//			added.
+//
+//			The first 8-bytes of each entry are guaranteed to be unique, and are used to identify table
+//			entries (list order, above, refers to a sort on the first 8-bytes). The OLT deletes a table
+//			entry by setting all of its last 8-bytes to 0xFF.
+//
+//			When the table is created, the ONU should autonomously predefine three entries that list the
+//			default treatment (normal forwarding without filtering or modification) for untagged, single
+//			tagged, and double tagged frames. As an exception to the rule on ordered processing, these
+//			default rules are always considered as a last resort for frames that do not match any other
+//			rule. Best practice dictates that these entries not be deleted by the OLT; however, they can be
+//			modified to produce the desired default behaviour.
+//
+//			It should be noted that downstream frame treatment is defined by the downstream mode attribute
+//			and is not affected by the upstream default rules.
+//
+//			15, 4096, x, 15, 4096, x, 0, (0, 15, x, x, 15, x, x) - no tags
+//
+//			15, 4096, x, 14, 4096, x, 0, (0, 15, x, x, 15, x, x) - 1 tag
+//
+//			14, 4096, x, 14, 4096, x, 0, (0, 15, x, x, 15, x, x) - 2 tags
+//
+//			NOTE 2 - x is a "don't care" field and should be set to zero.
+//
+//			See Figure 9.3.13-1.
+//
+//			(R,-W) (mandatory) (16N bytes, where N is the number of VLAN tagging rules)
+//
+//			Filter outer priority: (4 bits) Defines the outer VLAN priority filtering operation. The
+//			following values are supported:
+//
+//			0..7	Filter received frames on this outer priority (P bit) value.
+//
+//			8	Do not filter on outer priority.
+//
+//			14	This is the default filter when no other two-tag rule applies.
+//
+//			15	This entry is not a double-tag rule; ignore all other outer tag filter fields.
+//
+//			Other values: reserved.
+//
+//			Filter outer VID: (13 bits) Defines the outer VLAN VID filtering operation.  The following
+//			values are supported:
+//
+//			0..4094	Filter received frames on this outer VID value.
+//
+//			4096	Do not filter on the outer VID.
+//
+//			Other values: reserved.
+//
+//			Filter outer TPID/DEI: (3 bits) Defines the outer VLAN TPID/DEI filtering operation. The
+//			following values are supported:
+//
+//			000	Do not filter on outer TPID field.
+//
+//			100	Outer TPID = 0x8100. Filter on frames with the outer TPID set to 0x8100.
+//
+//			101	Outer TPID = input TPID attribute value, don't care about DEI bit. Filter on frames with the
+//			outer TPID set to match the Extended VLAN tagging operation configuration data Input TPID
+//			attribute value and ignore the DEI bit.
+//
+//			110	Outer TPID = input TPID, DEI = 0. Filter on frames with the outer TPID set to match the
+//			Extended VLAN tagging operation configuration data Input TPID attribute value and DEI set to the
+//			value 0.
+//
+//			111	Outer TPID = input TPID, DEI = 1. Filter on frames with the outer TPID set to match the
+//			Extended VLAN tagging operation configuration data Input TPID attribute value and DEI set to the
+//			value 1
+//
+//			Padding: (12 bits)
+//
+//			Filter inner priority: (4 bits) Defines the inner VLAN priority filtering operation.  The
+//			following values are supported:
+//
+//			0..7	Filter received frames on this inner priority value.
+//
+//			8	Do not filter on inner priority.
+//
+//			14	This is the default filter when no other one-tag rule applies.
+//
+//			15	This entry is a no-tag rule; ignore all other VLAN tag filter fields.
+//
+//			Other values: reserved.
+//
+//			Filter inner VID: (13 bits) Defines the inner VLAN VID filtering operation.  The following
+//			values are supported:
+//
+//			0..4094	Filter received frames on this inner VID value.
+//
+//			4096	Do not filter on the inner VID.
+//
+//			Other values: reserved.
+//
+//			Filter inner TPID/DEI: (3 bits) Defines the inner VLAN TPID/DEI filtering operation. The
+//			following values are supported:
+//
+//			000	Do not filter on inner TPID field.
+//
+//			100	Inner TPID = 0x8100. Filter on frames with the inner TPID set to 0x8100.
+//
+//			101	Inner TPID = input TPID attribute value, don't care about DEI bit. Filter on frames with the
+//			inner TPID set to match the Extended VLAN tagging operation configuration data Input TPID
+//			attribute value and ignore the DEI bit.
+//
+//			110	Inner TPID = input TPID, DEI = 0. Filter on frames with the inner TPID set to match the
+//			Extended VLAN tagging operation configuration data Input TPID attribute value and DEI set to the
+//			value 0.
+//
+//			111	Inner TPID = input TPID, DEI = 1. Filter on frames with the inner TPID set to match the
+//			Extended VLAN tagging operation configuration data Input TPID attribute value and DEI set to the
+//			value 1.
 //
 //		Associated Me Pointer
+//			This attribute points to the ME with which this extended VLAN tagging operation configuration
+//			data ME is associated. (R,-W, setbycreate) (mandatory) (2-bytes)
+//
 //			NOTE 5 - When the association type is xDSL, the two MSBs may be used to indicate a bearer
 //			channel.
 //
 //		Dscp To P Bit Mapping
+//			DSCP to P-bit mapping: This attribute specifies mapping from DSCP to P bits. The attribute can
+//			be considered a bit string sequence of 64 3-bit groups. The 64 sequence entries represent the
+//			possible values of the 6-bit DSCP field. Each 3-bit group specifies the P-bit value to which the
+//			associated DSCP value should be mapped. (R,-W) (optional) (24-bytes)
+//
 //			NOTE 6 - If certain bits in the DSCP field are to be ignored in the mapping process, the
 //			attribute should be provisioned such that all possible values of those bits produce the same
 //			P-bit mapping. This can be applied to the case where instead of full DSCP, the operator wishes
 //			to adopt the priority mechanism based on IP precedence, which needs only the three MSBs of the
 //			DSCP field.
 //
+//		Enhanced Mode
+//			The Boolean value true specifies that the Enhanced received frame classification and processing
+//			table is used, and the Received frame VLAN tagging operation table is ignored. The value false
+//			indicates the Enhanced received frame classification and processing table is not used. It is
+//			strongly recommended that the OLT uses the same value for all Extended VLAN tagging operation
+//			configuration data instances created on an ONU. (R, Setbycreate) (optional) (1-byte)
+//
+//		Enhanced Received Frame Classification And Processing Table
+//			This attribute is a table that provides enhanced capability for frame classification and
+//			processing. It extends the Received frame VLAN tagging operation table attribute with a set
+//			control field, a row key and direction. Each incoming packet is matched against each rule in row
+//			key order (smaller value row key has higher precedence) and direction. The first rule that
+//			matches the packet is selected as the active rule, and the packet is then treated according to
+//			that rule.
+//
+//			When the table is empty, the ONU discards all received frames. The OLT may choose to create
+//			three entries that list the default treatment (normal forwarding without filtering or
+//			modification) for untagged, single tagged, and double tagged frames, with the direction field
+//			set to 0.
+//
+//			NOTE 7 - Where no change is noted, the definitions in the Received frame VLAN tagging operation
+//			table attribute remain applicable.
+//
+//			(R,-W) (optional) (28N bytes, where N is the number of entries in the table).
+//
+//			Set ctrl: (2 bits)
+//
+//			This field determines the meaning of a set operation. These bits are returned as 00 during get
+//			next operations.
+//
+//			1	Write this entry into the table. Overwrite any existing entry with the same row key.
+//
+//			2	Delete this entry from the table. The remaining fields are not meaningful.
+//
+//			NOTE 8 - unlike the delete operation in the Received frame VLAN tagging operation table, the OLT
+//			does not need to set all eight bytes in Word 4 and Word 5 to 0xFF.
+//
+//			3	Clear all entries from the table. The remaining fields are not meaningful.
+//
+//			Other values: reserved.
+//
+//			Dir: (2 bits)
+//
+//			This field determines the direction of the classification and processing rule.
+//
+//			0	This is an upstream rule. In the downstream direction, the inverse classification and
+//			operation is defined based on the downstream mode code point. All downstream mode codepoints are
+//			considered valid to be used when dir=0 is used (including downstream  mode 8).
+//
+//			1	This is an upstream-only rule. This rule is ignored in the downstream direction.
+//
+//			2	This is a downstream-only rule. This rule is ignored in the upstream direction.
+//
+//			Other values: reserved.
+//
+//			Row key: (16 bits)
+//
+//			The row key distinguishes rows in the table. It is the responsibility of the OLT to assign and
+//			track row keys and content, and to ensure the classification rules are not duplicated and in the
+//			correct ordering.
+//
+//			For Filter outer priority, Filter outer VID, Filter outer TPID/DEI, Filter inner priority,
+//			Filter inner VID, Filter inner TPID/DEI, Filter on Extended Criteria, Filter Ethertype,
+//			Treatment outer priority, Treatment outer VID, Treatment outer TPID/DEI, Treatment inner
+//			priority, Treatment inner VID, and Treatment inner TPID/DEI values please refer to Received
+//			frame VLAN tagging operation table in this ME.
+//
 type ExtendedVlanTaggingOperationConfigurationData struct {
 	ManagedEntityDefinition
 	Attributes AttributeValueMap
@@ -106,17 +566,19 @@
 			Set,
 			SetTable,
 		),
-		AllowedAttributeMask: 0xff00,
+		AllowedAttributeMask: 0xffc0,
 		AttributeDefinitions: AttributeDefinitionMap{
-			0: Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read, SetByCreate), false, false, false, 0),
-			1: ByteField("AssociationType", EnumerationAttributeType, 0x8000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 1),
-			2: Uint16Field("ReceivedFrameVlanTaggingOperationTableMaxSize", UnsignedIntegerAttributeType, 0x4000, 0, mapset.NewSetWith(Read), false, false, false, 2),
-			3: Uint16Field("InputTpid", UnsignedIntegerAttributeType, 0x2000, 34984, mapset.NewSetWith(Read, Write), false, false, false, 3),
-			4: Uint16Field("OutputTpid", UnsignedIntegerAttributeType, 0x1000, 34984, mapset.NewSetWith(Read, Write), false, false, false, 4),
-			5: ByteField("DownstreamMode", EnumerationAttributeType, 0x0800, 0, mapset.NewSetWith(Read, Write), false, false, false, 5),
-			6: TableField("ReceivedFrameVlanTaggingOperationTable", TableAttributeType, 0x0400, TableInfo{nil, 16}, mapset.NewSetWith(Read, Write), false, false, false, 6),
-			7: Uint16Field("AssociatedMePointer", PointerAttributeType, 0x0200, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 7),
-			8: MultiByteField("DscpToPBitMapping", OctetsAttributeType, 0x0100, 24, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), mapset.NewSetWith(Read, Write), false, true, false, 8),
+			0:  Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read, SetByCreate), false, false, false, 0),
+			1:  ByteField("AssociationType", EnumerationAttributeType, 0x8000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 1),
+			2:  Uint16Field("ReceivedFrameVlanTaggingOperationTableMaxSize", UnsignedIntegerAttributeType, 0x4000, 0, mapset.NewSetWith(Read), false, false, false, 2),
+			3:  Uint16Field("InputTpid", UnsignedIntegerAttributeType, 0x2000, 34984, mapset.NewSetWith(Read, Write), false, false, false, 3),
+			4:  Uint16Field("OutputTpid", UnsignedIntegerAttributeType, 0x1000, 34984, mapset.NewSetWith(Read, Write), false, false, false, 4),
+			5:  ByteField("DownstreamMode", EnumerationAttributeType, 0x0800, 0, mapset.NewSetWith(Read, Write), false, false, false, 5),
+			6:  TableField("ReceivedFrameVlanTaggingOperationTable", TableAttributeType, 0x0400, TableInfo{nil, 16}, mapset.NewSetWith(Read, Write), false, false, false, 6),
+			7:  Uint16Field("AssociatedMePointer", PointerAttributeType, 0x0200, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 7),
+			8:  MultiByteField("DscpToPBitMapping", OctetsAttributeType, 0x0100, 24, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), mapset.NewSetWith(Read, Write), false, true, false, 8),
+			9:  ByteField("EnhancedMode", UnsignedIntegerAttributeType, 0x0080, 0, mapset.NewSetWith(Read, SetByCreate), false, true, false, 9),
+			10: TableField("EnhancedReceivedFrameClassificationAndProcessingTable", TableAttributeType, 0x0040, TableInfo{nil, 28}, mapset.NewSetWith(Read, Write), false, true, false, 10),
 		},
 		Access:  CreatedByOlt,
 		Support: UnknownSupport,
diff --git a/generated/fastchannelconfigurationprofile.go b/generated/fastchannelconfigurationprofile.go
index e1ccdea..72d15d6 100644
--- a/generated/fastchannelconfigurationprofile.go
+++ b/generated/fastchannelconfigurationprofile.go
@@ -27,11 +27,11 @@
 
 // FastChannelConfigurationProfileClassID is the 16-bit ID for the OMCI
 // Managed entity FAST channel configuration profile
-const FastChannelConfigurationProfileClassID ClassID = ClassID(432)
+const FastChannelConfigurationProfileClassID = ClassID(432) // 0x01b0
 
 var fastchannelconfigurationprofileBME *ManagedEntityDefinition
 
-// FastChannelConfigurationProfile (class ID #432)
+// FastChannelConfigurationProfile (Class ID: #432 / 0x01b0)
 //	This ME contains the FAST channel configuration profile for an xDSL UNI. An instance of this ME
 //	is created and deleted by the OLT.
 //
@@ -93,6 +93,20 @@
 //			[ITU-T G.997.2]. (R, W) (mandatory) (1 byte)
 //
 //		Rein Inter_Arrival Time Iat_Rein
+//			REIN Inter-arrival time (IAT_REIN): This attribute specifies the REIN IAT. See clause 9.8 of
+//			[ITU-T G.9701]. The ITU-T G.9701 control parameter iat_rein_flag is set to the same value as the
+//			REIN IAT. See clause 11.4.2.7 of [ITU-T G.9701].
+//
+//			The REIN IAT is specified via the following values:
+//
+//			1	100 Hz;
+//
+//			2	120 Hz;
+//
+//			3	360 Hz.
+//
+//			See clause 7.2.2.5 of [ITU-T G.997.2].
+//
 //			(R, W) (mandatory) (1 byte)
 //
 //		Minimum Reed_Solomon Rfec_Nfec Ratio Rnratio
diff --git a/generated/fastdatapathconfigurationprofile.go b/generated/fastdatapathconfigurationprofile.go
index cd6ac4e..f7d9546 100644
--- a/generated/fastdatapathconfigurationprofile.go
+++ b/generated/fastdatapathconfigurationprofile.go
@@ -27,11 +27,11 @@
 
 // FastDataPathConfigurationProfileClassID is the 16-bit ID for the OMCI
 // Managed entity FAST data path configuration profile
-const FastDataPathConfigurationProfileClassID ClassID = ClassID(433)
+const FastDataPathConfigurationProfileClassID = ClassID(433) // 0x01b1
 
 var fastdatapathconfigurationprofileBME *ManagedEntityDefinition
 
-// FastDataPathConfigurationProfile (class ID #433)
+// FastDataPathConfigurationProfile (Class ID: #433 / 0x01b1)
 //	This ME contains FAST the data path configuration profile for an xDSL UNI. An instance of this
 //	ME is created and deleted by the OLT.
 //
@@ -41,8 +41,8 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The value 0 is
-//			reserved. (R, set-by-create) (mandatory) (2 bytes)
+//			This attribute uniquely identifies each instance of this ME. The value 0 is reserved. (R, set-
+//			by-create) (mandatory) (2 bytes)
 //
 //		Tps_Tc Testmode Tps_Testmode
 //			TPS-TC testmode (TPS_TESTMODE): This Boolean attribute specifies whether the TPSTC test mode
diff --git a/generated/fastlineinventoryandstatusdatapart2.go b/generated/fastlineinventoryandstatusdatapart2.go
index fe876cc..ae25b7f 100644
--- a/generated/fastlineinventoryandstatusdatapart2.go
+++ b/generated/fastlineinventoryandstatusdatapart2.go
@@ -27,11 +27,11 @@
 
 // FastLineInventoryAndStatusDataPart2ClassID is the 16-bit ID for the OMCI
 // Managed entity FAST line inventory and status data part 2
-const FastLineInventoryAndStatusDataPart2ClassID ClassID = ClassID(436)
+const FastLineInventoryAndStatusDataPart2ClassID = ClassID(436) // 0x01b4
 
 var fastlineinventoryandstatusdatapart2BME *ManagedEntityDefinition
 
-// FastLineInventoryAndStatusDataPart2 (class ID #436)
+// FastLineInventoryAndStatusDataPart2 (Class ID: #436 / 0x01b4)
 //	This ME contains part 3 of the FAST line inventory and status data with attributes specific to
 //	[ITU T G.997.2]. The ONU automatically creates or deletes an instance of this ME upon the
 //	creation or deletion of a PPTP xDSL UNI part 1.
@@ -43,11 +43,15 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP xDSL UNI part 1. (R)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP xDSL UNI part 1. (R) (mandatory) (2-bytes)
 //
 //		Date_Time_Stamping Of Last Successful Downstream Fra Operation Stamp_Frads
+//			Date/time-stamping of last successful downstream FRA operation (STAMP-FRAds): This attribute
+//			reports the date/time of the last successful FTU-R initiated FRA execution that has modified the
+//			bits allocation. See clause 7.10.14.5 of [ITUT-G.997.2]. The format of this parameter is as
+//			follows:
+//
 //			(R) (optional) (7 bytes)
 //
 //		Date_Time_Stamping Of Last Successful Upstream Fra Operation Stamp_Fraus
diff --git a/generated/fastvectoringlineconfigurationextensions.go b/generated/fastvectoringlineconfigurationextensions.go
index b218d3d..acbe8d3 100644
--- a/generated/fastvectoringlineconfigurationextensions.go
+++ b/generated/fastvectoringlineconfigurationextensions.go
@@ -27,11 +27,11 @@
 
 // FastVectoringLineConfigurationExtensionsClassID is the 16-bit ID for the OMCI
 // Managed entity FAST vectoring line configuration extensions
-const FastVectoringLineConfigurationExtensionsClassID ClassID = ClassID(434)
+const FastVectoringLineConfigurationExtensionsClassID = ClassID(434) // 0x01b2
 
 var fastvectoringlineconfigurationextensionsBME *ManagedEntityDefinition
 
-// FastVectoringLineConfigurationExtensions (class ID #434)
+// FastVectoringLineConfigurationExtensions (Class ID: #434 / 0x01b2)
 //	This ME extends FAST line configuration MEs with attributes that are specific to vectoring. An
 //	instance of this ME is created and deleted by the OLT.
 //
@@ -42,8 +42,8 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The value 0 is
-//			reserved. (R, set-by-create) (mandatory) (2 bytes)
+//			This attribute uniquely identifies each instance of this ME. The value 0 is reserved. (R, set-
+//			by-create) (mandatory) (2 bytes)
 //
 //		Fext Cancellation Enabling_Disabling Upstream Fext_To_Cancel_Enableus
 //			FEXT cancellation enabling/disabling upstream (FEXT_TO_CANCEL_ENABLEus): A value of 1 enables
diff --git a/generated/fastxtu-cperformancemonitoringhistorydata.go b/generated/fastxtu-cperformancemonitoringhistorydata.go
index 16c2114..0c2d554 100644
--- a/generated/fastxtu-cperformancemonitoringhistorydata.go
+++ b/generated/fastxtu-cperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // FastXtuCPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity FAST xTU-C performance monitoring history data
-const FastXtuCPerformanceMonitoringHistoryDataClassID ClassID = ClassID(437)
+const FastXtuCPerformanceMonitoringHistoryDataClassID = ClassID(437) // 0x01b5
 
 var fastxtucperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// FastXtuCPerformanceMonitoringHistoryData (class ID #437)
+// FastXtuCPerformanceMonitoringHistoryData (Class ID: #437 / 0x01b5)
 //	This ME collects PM data on the xTU C to xTU R path as seen from the xTU-C. Instances of this ME
 //	are created and deleted by the OLT.
 //
@@ -40,33 +40,32 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP xDSL UNI part 1. (R, set-
-//			by-create) (mandatory) (2 bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP xDSL UNI part 1. (R, set-by-create) (mandatory) (2
+//			bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1 byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1 byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 and 2 MEs
 //			that contain PM threshold values. (R, W, set-by-create) (mandatory) (2 bytes)
 //
 //		Successful Fra Counter
-//			Successful FRA counter: This attribute counts the successful FRA primitives (success_FRA). The
-//			successful FRA primitive (success_FRA) is defined in clause 11.3.1.6 of [ITU-T G.9701]. See
-//			clause 7.7.22 of [ITU-T G.997.2]. (R) (mandatory) (4-bytes)
+//			This attribute counts the successful FRA primitives (success_FRA). The successful FRA primitive
+//			(success_FRA) is defined in clause 11.3.1.6 of [ITU-T G.9701]. See clause 7.7.22 of [ITU-T
+//			G.997.2]. (R) (mandatory) (4-bytes)
 //
 //		Successful Rpa Counter
-//			Successful RPA counter: This attribute counts the successful RPA primitives (success_RPA). The
-//			successful RPA primitive (success_RPA) is defined in clause 11.3.1.6 of [ITU-T G.9701]. See
-//			clause 7.7.23 of [ITU-T G.997.2] (R) (optional) (4 bytes)
+//			This attribute counts the successful RPA primitives (success_RPA). The successful RPA primitive
+//			(success_RPA) is defined in clause 11.3.1.6 of [ITU-T G.9701]. See clause 7.7.23 of [ITU-T
+//			G.997.2] (R) (optional) (4 bytes)
 //
 //		Successful Tiga Counter
-//			Successful TIGA counter: This attribute counts the successful TIGA primitives (success_TIGA).
-//			The successful TIGA primitive (success_TIGA) is defined in clause 11.3.1.6 of [ITU-T G.9701].
-//			Reported only with the near-end measured time, invalid data flag and timestamp. See clause
-//			7.7.24 of [ITUT-G.997.2] (R) (optional) (4 bytes)
+//			This attribute counts the successful TIGA primitives (success_TIGA). The successful TIGA
+//			primitive (success_TIGA) is defined in clause 11.3.1.6 of [ITU-T G.9701]. Reported only with the
+//			near-end measured time, invalid data flag and timestamp. See clause 7.7.24 of [ITUT-G.997.2] (R)
+//			(optional) (4 bytes)
 //
 type FastXtuCPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/fastxtu-rperformancemonitoringhistorydata.go b/generated/fastxtu-rperformancemonitoringhistorydata.go
index ff8741b..579f46f 100644
--- a/generated/fastxtu-rperformancemonitoringhistorydata.go
+++ b/generated/fastxtu-rperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // FastXtuRPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity FAST xTU-R performance monitoring history data
-const FastXtuRPerformanceMonitoringHistoryDataClassID ClassID = ClassID(438)
+const FastXtuRPerformanceMonitoringHistoryDataClassID = ClassID(438) // 0x01b6
 
 var fastxturperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// FastXtuRPerformanceMonitoringHistoryData (class ID #438)
+// FastXtuRPerformanceMonitoringHistoryData (Class ID: #438 / 0x01b6)
 //	This ME collects PM data of the xTU C to xTU R path as seen from the xTU-R. Instances of this ME
 //	are created and deleted by the OLT. For a complete discussion of generic PM architecture, refer
 //	to clause I.4.
@@ -41,27 +41,26 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP xDSL UNI part 1. (R, set-
-//			by-create) (mandatory) (2 bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP xDSL UNI part 1. (R, set-by-create) (mandatory) (2
+//			bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1 byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1 byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 and 2 MEs
 //			that contain PM threshold values. (R, W, set-by-create) (mandatory) (2 bytes)
 //
 //		Successful Fra Counter
-//			Successful FRA counter: This attribute counts the successful FRA primitives (success_FRA). The
-//			successful FRA primitive (success_FRA) is defined in clause 11.3.1.6 of [ITU-T G.9701]. See
-//			clause 7.7.22 of [ITU-T G.997.2] (R) (mandatory) (4-bytes)
+//			This attribute counts the successful FRA primitives (success_FRA). The successful FRA primitive
+//			(success_FRA) is defined in clause 11.3.1.6 of [ITU-T G.9701]. See clause 7.7.22 of [ITU-T
+//			G.997.2] (R) (mandatory) (4-bytes)
 //
 //		Successful Rpa Counter
-//			Successful RPA counter: This attribute counts the successful RPA primitives (success_RPA). The
-//			successful RPA primitive (success_RPA) is defined in clause 11.3.1.6 of [ITU-T G.9701]. See
-//			clause 7.7.23 of [ITU-T G.997.2] (R) (optional) (4 bytes)
+//			This attribute counts the successful RPA primitives (success_RPA). The successful RPA primitive
+//			(success_RPA) is defined in clause 11.3.1.6 of [ITU-T G.9701]. See clause 7.7.23 of [ITU-T
+//			G.997.2] (R) (optional) (4 bytes)
 //
 type FastXtuRPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/fecperformancemonitoringhistorydata.go b/generated/fecperformancemonitoringhistorydata.go
index b990013..1633e36 100644
--- a/generated/fecperformancemonitoringhistorydata.go
+++ b/generated/fecperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // FecPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity FEC performance monitoring history data
-const FecPerformanceMonitoringHistoryDataClassID ClassID = ClassID(312)
+const FecPerformanceMonitoringHistoryDataClassID = ClassID(312) // 0x0138
 
 var fecperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// FecPerformanceMonitoringHistoryData (class ID #312)
+// FecPerformanceMonitoringHistoryData (Class ID: #312 / 0x0138)
 //	This ME collects PM data associated with PON downstream forward error correction (FEC) counters.
 //	Instances of this ME are created and deleted by the OLT.
 //
@@ -43,13 +43,12 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the ANI-G or a TWDM channel. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the ANI-G or a TWDM channel. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -57,23 +56,22 @@
 //			data 2 ME is optional. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Corrected Bytes
-//			Corrected bytes: This attribute counts the number of bytes that were corrected by the FEC
-//			function. (R) (mandatory) (4-bytes)
+//			This attribute counts the number of bytes that were corrected by the FEC function. (R)
+//			(mandatory) (4-bytes)
 //
 //		Corrected Code Words
-//			Corrected code words: This attribute counts the code words that were corrected by the FEC
-//			function. (R) (mandatory) (4-bytes)
+//			This attribute counts the code words that were corrected by the FEC function. (R) (mandatory)
+//			(4-bytes)
 //
 //		Uncorrectable Code Words
-//			Uncorrectable code words: This attribute counts errored code words that could not be corrected
-//			by the FEC function. (R) (mandatory) (4-bytes)
+//			This attribute counts errored code words that could not be corrected by the FEC function. (R)
+//			(mandatory) (4-bytes)
 //
 //		Total Code Words
-//			Total code words: This attribute counts the total received code words. (R) (mandatory) (4-bytes)
+//			This attribute counts the total received code words. (R) (mandatory) (4-bytes)
 //
 //		Fec Seconds
-//			FEC seconds:	This attribute counts seconds during which there was an FEC anomaly. (R)
-//			(mandatory) (2-bytes)
+//			This attribute counts seconds during which there was an FEC anomaly. (R) (mandatory) (2-bytes)
 //
 type FecPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/galethernetperformancemonitoringhistorydata.go b/generated/galethernetperformancemonitoringhistorydata.go
index edd9a89..808da29 100644
--- a/generated/galethernetperformancemonitoringhistorydata.go
+++ b/generated/galethernetperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // GalEthernetPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity GAL Ethernet performance monitoring history data
-const GalEthernetPerformanceMonitoringHistoryDataClassID ClassID = ClassID(276)
+const GalEthernetPerformanceMonitoringHistoryDataClassID = ClassID(276) // 0x0114
 
 var galethernetperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// GalEthernetPerformanceMonitoringHistoryData (class ID #276)
+// GalEthernetPerformanceMonitoringHistoryData (Class ID: #276 / 0x0114)
 //	This ME collects PM data associated with a GEM IW TP when the GEM layer supports an Ethernet
 //	service. Instances of this ME are created and deleted by the OLT.
 //
@@ -42,13 +42,11 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the GEM IW TP. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the GEM IW TP. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -56,9 +54,8 @@
 //			data 2 ME is optional. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Discarded Frames
-//			Discarded frames: This attribute counts the number of downstream GEM frames discarded for any
-//			reason [erroneous frame check sequence (FCS), too long length, buffer overflow, etc.]. (R)
-//			(mandatory) (4-bytes)
+//			This attribute counts the number of downstream GEM frames discarded for any reason [erroneous
+//			frame check sequence (FCS), too long length, buffer overflow, etc.]. (R) (mandatory) (4-bytes)
 //
 type GalEthernetPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/galethernetprofile.go b/generated/galethernetprofile.go
index 877bad0..9521dc6 100644
--- a/generated/galethernetprofile.go
+++ b/generated/galethernetprofile.go
@@ -27,11 +27,11 @@
 
 // GalEthernetProfileClassID is the 16-bit ID for the OMCI
 // Managed entity GAL Ethernet profile
-const GalEthernetProfileClassID ClassID = ClassID(272)
+const GalEthernetProfileClassID = ClassID(272) // 0x0110
 
 var galethernetprofileBME *ManagedEntityDefinition
 
-// GalEthernetProfile (class ID #272)
+// GalEthernetProfile (Class ID: #272 / 0x0110)
 //	This ME organizes data that describe the gigabit-capable passive optical network transmission
 //	convergence layer (GTC) adaptation layer processing functions of the ONU for Ethernet services.
 //	It is used with the GEM IW TP ME.
@@ -43,12 +43,12 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Maximum Gem Payload Size
-//			Maximum GEM payload size: This attribute defines the maximum payload size generated in the
-//			associated GEM IW TP ME. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute defines the maximum payload size generated in the associated GEM IW TP ME. (R,-W,
+//			setbycreate) (mandatory) (2-bytes)
 //
 type GalEthernetProfile struct {
 	ManagedEntityDefinition
diff --git a/generated/geminterworkingterminationpoint.go b/generated/geminterworkingterminationpoint.go
index 6b84a21..575d6f9 100644
--- a/generated/geminterworkingterminationpoint.go
+++ b/generated/geminterworkingterminationpoint.go
@@ -27,11 +27,11 @@
 
 // GemInterworkingTerminationPointClassID is the 16-bit ID for the OMCI
 // Managed entity GEM interworking termination point
-const GemInterworkingTerminationPointClassID ClassID = ClassID(266)
+const GemInterworkingTerminationPointClassID = ClassID(266) // 0x010a
 
 var geminterworkingterminationpointBME *ManagedEntityDefinition
 
-// GemInterworkingTerminationPoint (class ID #266)
+// GemInterworkingTerminationPoint (Class ID: #266 / 0x010a)
 //	An instance of this ME represents a point in the ONU where the IW of a bearer service (usually
 //	Ethernet) to the GEM layer takes place. At this point, GEM packets are generated from the bearer
 //	bit stream (e.g., Ethernet) or the bearer bit stream is reconstructed from GEM packets.
@@ -44,36 +44,105 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Gem Port Network Ctp Connectivity Pointer
-//			GEM port network CTP connectivity pointer: This attribute points to an instance of the GEM port
-//			network CTP. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute points to an instance of the GEM port network CTP. (R,-W, setbycreate)
+//			(mandatory) (2-bytes)
 //
 //		Interworking Option
+//			This attribute identifies the type of non-GEM function that is being interworked. The options
+//			are as follows.
+//
+//			0	Circuit-emulated TDM
+//
+//			1	MAC bridged LAN
+//
+//			2	Reserved
+//
+//			3	Reserved
+//
+//			4	Video return path
+//
+//			5	IEEE 802.1p mapper
+//
+//			6	Downstream broadcast
+//
+//			7	MPLS PW TDM service
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Service Profile Pointer
+//			This attribute points to an instance of a service profile:
+//
+//			CES service profile	if IW option-=-0
+//
+//			MAC bridge service profile	if IW option-=-1
+//
+//			Video return path service profile	if IW option-=-4
+//
+//			IEEE 802.1p mapper service profile	if IW option-=-5
+//
+//			Null pointer	if IW option-=-6
+//
+//			CES service profile	if IW option-=-7
+//
+//			(R,-W, setbycreate) (mandatory) (2-bytes)
+//
 //			NOTE - The video return path (VRP) service profile is defined in [ITU-T G.984.4].
 //
 //		Interworking Termination Point Pointer
+//			This attribute is used for the CES and IEEE 802.1p mapper service without a MAC bridge.
+//			Depending on the service provided, it points to the associated instance of the following MEs:
+//
+//			PPTP CES UNI
+//
+//			Logical N * 64 kbit/s sub-port CTP
+//
+//			PPTP Ethernet UNI
+//
 //			In all other GEM services, the relationship between the related service TP and this GEM IW TP is
 //			derived from other ME relations; this attribute is set to a null pointer and not used. (R,-W,
 //			setbycreate) (mandatory) (2-bytes)
 //
 //		Pptp Counter
-//			PPTP counter: This value reports the number of PPTP ME instances associated with this GEM IW TP.
-//			(R) (optional) (1-byte)
+//			This value reports the number of PPTP ME instances associated with this GEM IW TP. (R)
+//			(optional) (1-byte)
 //
 //		Operational State
-//			Operational state: This attribute indicates whether the ME is capable of performing its
-//			function. Valid values are enabled (0) and disabled (1). (R) (optional) (1-byte)
+//			This attribute indicates whether the ME is capable of performing its function. Valid values are
+//			enabled (0) and disabled (1). (R) (optional) (1-byte)
 //
 //		Gal Profile Pointer
+//			5	GAL Ethernet profile for IEEE 802.1p mapper
+//
+//			6	Null pointer
+//
+//			7	Null pointer
+//
 //			(R,-W, setbycreate) (mandatory) (2-bytes)
 //
+//			This attribute points to an instance of the GAL profile. The relationship between the IW option
+//			and the related GAL profile is as follows.
+//
+//			Interworking option	GAL profile type
+//
+//			0	Null pointer
+//
+//			1	GAL Ethernet profile
+//
+//			3	GAL Ethernet profile for data service
+//
+//			4	GAL Ethernet profile for video return path
+//
 //		Gal Loopback Configuration
+//			This attribute sets the loopback configuration when using GEM mode:
+//
+//			0	No loopback
+//
+//			1	Loopback of downstream traffic after GAL
+//
 //			The default value of this attribute is 0. When the IW option is 6 (downstream broadcast), this
 //			attribute is not used. (R,-W) (mandatory) (1-byte)
 //
diff --git a/generated/gemportnetworkctp.go b/generated/gemportnetworkctp.go
index be1c163..627e052 100644
--- a/generated/gemportnetworkctp.go
+++ b/generated/gemportnetworkctp.go
@@ -27,11 +27,11 @@
 
 // GemPortNetworkCtpClassID is the 16-bit ID for the OMCI
 // Managed entity GEM port network CTP
-const GemPortNetworkCtpClassID ClassID = ClassID(268)
+const GemPortNetworkCtpClassID = ClassID(268) // 0x010c
 
 var gemportnetworkctpBME *ManagedEntityDefinition
 
-// GemPortNetworkCtp (class ID #268)
+// GemPortNetworkCtp (Class ID: #268 / 0x010c)
 //	This ME represents the termination of a GEM port on an ONU. This ME aggregates connectivity
 //	functionality from the network view and alarms from the network element view as well as
 //	artefacts from trails.
@@ -56,10 +56,13 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Port_Id
+//			Port-ID:	This attribute is the port-ID of the GEM port associated with this CTP. (RWSC)
+//			(mandatory) (2-bytes)
+//
 //			NOTE 1 - While nothing forbids the existence of several GEM port network CTPs with the same
 //			port-ID value, downstream traffic is modelled as being delivered to all such GEM port network
 //			CTPs. Be aware of potential difficulties associated with defining downstream flows and
@@ -70,38 +73,73 @@
 //			(2-bytes)
 //
 //		Direction
-//			Direction:	This attribute specifies whether the GEM port is used for UNI-to-ANI (1), ANI-to-UNI
-//			(2), or bidirectional (3) connection. (R,-W, setbycreate) (mandatory) (1-byte)
+//			This attribute specifies whether the GEM port is used for UNI-to-ANI (1), ANI-to-UNI (2), or
+//			bidirectional (3) connection. (R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Traffic Management Pointer For Upstream
-//			Traffic management pointer for upstream: If the traffic management option attribute in the ONU-G
-//			ME is 0 (priority controlled) or 2 (priority and rate controlled), this pointer specifies the
-//			priority queue ME serving this GEM port network CTP. If the traffic management option attribute
-//			is 1 (rate controlled), this attribute redundantly points to the TCONT serving this GEM port
-//			network CTP. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			If the traffic management option attribute in the ONU-G ME is 0 (priority controlled) or 2
+//			(priority and rate controlled), this pointer specifies the priority queue ME serving this GEM
+//			port network CTP. If the traffic management option attribute is 1 (rate controlled), this
+//			attribute redundantly points to the TCONT serving this GEM port network CTP. (R,-W, setbycreate)
+//			(mandatory) (2-bytes)
 //
 //		Traffic Descriptor Profile Pointer For Upstream
 //			See also Appendix II.
 //
+//			This attribute points to the instance of the traffic descriptor ME that contains the upstream
+//			traffic parameters for this GEM port network CTP. This attribute is used when the traffic
+//			management option attribute in the ONU-G ME is 1 (rate controlled), specifying the PIR/PBS to
+//			which the upstream traffic is shaped. This attribute is also used when the traffic management
+//			option attribute in the ONU-G ME is 2 (priority and rate controlled), specifying the
+//			CIR/CBS/PIR/PBS to which the upstream traffic is policed. (R,-W, setbycreate) (optional)
+//			(2-bytes)
+//
 //		Uni Counter
-//			UNI counter: This attribute reports the number of instances of UNI-G ME associated with this GEM
-//			port network CTP. (R) (optional) (1-byte)
+//			This attribute reports the number of instances of UNI-G ME associated with this GEM port network
+//			CTP. (R) (optional) (1-byte)
 //
 //		Priority Queue Pointer For Down Stream
+//			Priority queue pointer for downstream: This attribute points to the instance of the priority
+//			queue used for this GEM port network CTP in the downstream direction. It is the responsibility
+//			of the OLT to provision the downstream pointer in a way that is consistent with the bridge and
+//			mapper connectivity. If the pointer is null, downstream queueing is determined by other
+//			mechanisms in the ONU. (R,-W, setbycreate) (mandatory) (2-bytes)
+//
 //			NOTE 2 - If the GEM port network CTP is associated with more than one UNI (downstream
 //			multicast), the downstream priority queue pointer defines a pattern (e.g., queue number 3 for a
 //			given UNI) to be replicated (i.e., to queue number 3) at the other affected UNIs.
 //
 //		Encryption State
-//			Encryption state: This attribute indicates the current state of the GEM port network CTP's
-//			encryption. Legal values are defined to be the same as those of the security mode attribute of
-//			the ONU2-G, with the exception that attribute value 0 indicates an unencrypted GEM port. (R)
-//			(optional) (1-byte)
+//			This attribute indicates the current state of the GEM port network CTP's encryption. Legal
+//			values are defined to be the same as those of the security mode attribute of the ONU2-G, with
+//			the exception that attribute value 0 indicates an unencrypted GEM port. (R) (optional) (1-byte)
 //
 //		Traffic Descriptor Profile Pointer For Downstream
+//			This attribute points to the instance of the traffic descriptor ME that contains the downstream
+//			traffic parameters for this GEM port network CTP. This attribute is used when the traffic
+//			management option attribute in the ONU-G ME is 1 (rate controlled), specifying the PIR/PBS to
+//			which the downstream traffic is shaped. This attribute is also used when the traffic management
+//			option attribute in the ONU-G ME is 2 (priority and rate controlled), specifying the
+//			CIR/CBS/PIR/PBS to which the downstream traffic is policed. (R,-W, setbycreate) (optional)
+//			(2-bytes)
+//
 //			See also Appendix II.
 //
 //		Encryption Key Ring
+//			This attribute is defined in ITU-T G.987 systems only. It specifies whether the associated GEM
+//			port is encrypted, and if so, which key ring it uses. (R, W, setbycreate) (optional) (1 byte)
+//
+//			0	(default) No encryption. The downstream key index is ignored, and upstream traffic is
+//			transmitted with key index 0.
+//
+//			1	Unicast payload encryption in both directions. Keys are generated by the ONU and transmitted
+//			to the OLT via the PLOAM channel.
+//
+//			2	Broadcast (multicast) encryption. Keys are generated by the OLT and distributed via the OMCI.
+//
+//			3	Unicast encryption, downstream only. Keys are generated by the ONU and transmitted to the OLT
+//			via the PLOAM channel.
+//
 //			Other values are reserved.
 //
 type GemPortNetworkCtp struct {
diff --git a/generated/gemportnetworkctpperformancemonitoringhistorydata.go b/generated/gemportnetworkctpperformancemonitoringhistorydata.go
index 069b25c..ec04ef9 100644
--- a/generated/gemportnetworkctpperformancemonitoringhistorydata.go
+++ b/generated/gemportnetworkctpperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity GEM port network CTP performance monitoring history data
-const GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID ClassID = ClassID(341)
+const GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID = ClassID(341) // 0x0155
 
 var gemportnetworkctpperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// GemPortNetworkCtpPerformanceMonitoringHistoryData (class ID #341)
+// GemPortNetworkCtpPerformanceMonitoringHistoryData (Class ID: #341 / 0x0155)
 //	This ME collects GEM frame PM data associated with a GEM port network CTP. Instances of this ME
 //	are created and deleted by the OLT.
 //
@@ -51,13 +51,12 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the GEM port network CTP. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the GEM port network CTP. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -65,26 +64,33 @@
 //			data 2 ME is optional. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Transmitted Gem Frames
-//			Transmitted GEM frames: This attribute counts GEM frames transmitted on the monitored GEM port.
-//			(R) (mandatory) (4-bytes)
+//			This attribute counts GEM frames transmitted on the monitored GEM port. (R) (mandatory)
+//			(4-bytes)
 //
 //		Received Gem Frames
-//			Received GEM frames: This attribute counts GEM frames received correctly on the monitored GEM
-//			port. A correctly received GEM frame is one that does not contain uncorrectable errors and has a
-//			valid header error check (HEC). (R) (mandatory) (4-bytes)
+//			This attribute counts GEM frames received correctly on the monitored GEM port. A correctly
+//			received GEM frame is one that does not contain uncorrectable errors and has a valid header
+//			error check (HEC). (R) (mandatory) (4-bytes)
 //
 //		Received Payload Bytes
-//			Received payload bytes: This attribute counts user payload bytes received on the monitored GEM
-//			port. (R) (mandatory) (8-bytes)
+//			This attribute counts user payload bytes received on the monitored GEM port. (R) (mandatory)
+//			(8-bytes)
 //
 //		Transmitted Payload Bytes
-//			Transmitted payload bytes: This attribute counts user payload bytes transmitted on the monitored
-//			GEM port. (R) (mandatory) (8-bytes)
+//			This attribute counts user payload bytes transmitted on the monitored GEM port. (R) (mandatory)
+//			(8-bytes)
 //
 //		Encryption Key Errors
+//			NOTE 3 - GEM PM ignores idle GEM frames.
+//
 //			NOTE 4 - GEM PM counts each non-idle GEM frame, whether it contains an entire user frame or only
 //			a fragment of a user frame.
 //
+//			This attribute is defined in ITU-T G.987 systems only. It counts GEM frames with erroneous
+//			encryption key indexes. If the GEM port is not encrypted, this attribute counts any frame with a
+//			key index not equal to 0. If the GEM port is encrypted, this attribute counts any frame whose
+//			key index specifies a key that is not known to the ONU. (R) (optional) (4-bytes)
+//
 type GemPortNetworkCtpPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
 	Attributes AttributeValueMap
diff --git a/generated/generalpurposebuffer.go b/generated/generalpurposebuffer.go
index cd323bf..90cd13e 100644
--- a/generated/generalpurposebuffer.go
+++ b/generated/generalpurposebuffer.go
@@ -27,11 +27,11 @@
 
 // GeneralPurposeBufferClassID is the 16-bit ID for the OMCI
 // Managed entity General purpose buffer
-const GeneralPurposeBufferClassID ClassID = ClassID(308)
+const GeneralPurposeBufferClassID = ClassID(308) // 0x0134
 
 var generalpurposebufferBME *ManagedEntityDefinition
 
-// GeneralPurposeBuffer (class ID #308)
+// GeneralPurposeBuffer (Class ID: #308 / 0x0134)
 //	This ME is created by the OLT when needed to store the results of an operation, such as a test
 //	command, that needs to return a block of data of indeterminate size. The buffer is retrieved
 //	with get next operations, since its size is not known a priori. An instance of this ME is
@@ -51,22 +51,22 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Maximum Size
-//			Maximum size: The ONU determines the actual size of the buffer table in the process of capturing
-//			the data directed to it. The maximum size attribute permits the OLT to restrict the maximum size
-//			of the buffer table. The value 0 indicates that the OLT imposes no limit on the size; it is
-//			recognized that ONU implementations will impose their own limits. The ONU will not create a
-//			buffer table larger than the value of this attribute. If the ONU cannot allocate enough memory
-//			to accommodate this size, it should deny the ME create action or a write operation that attempts
-//			to expand an existing ME. (R,-W, setbycreate) (optional) (4-bytes)
+//			The ONU determines the actual size of the buffer table in the process of capturing the data
+//			directed to it. The maximum size attribute permits the OLT to restrict the maximum size of the
+//			buffer table. The value 0 indicates that the OLT imposes no limit on the size; it is recognized
+//			that ONU implementations will impose their own limits. The ONU will not create a buffer table
+//			larger than the value of this attribute. If the ONU cannot allocate enough memory to accommodate
+//			this size, it should deny the ME create action or a write operation that attempts to expand an
+//			existing ME. (R,-W, setbycreate) (optional) (4-bytes)
 //
 //		Buffer Table
-//			Buffer table:	This attribute is an octet string that contains the result of some operation
-//			performed on the ONU. The exact content depends on the operation, and is documented with the
-//			definition of each operation. (R) (mandatory) (N bytes)
+//			This attribute is an octet string that contains the result of some operation performed on the
+//			ONU. The exact content depends on the operation, and is documented with the definition of each
+//			operation. (R) (mandatory) (N bytes)
 //
 type GeneralPurposeBuffer struct {
 	ManagedEntityDefinition
diff --git a/generated/ieee802.1pmapperserviceprofile.go b/generated/ieee802.1pmapperserviceprofile.go
index a98d619..989c783 100644
--- a/generated/ieee802.1pmapperserviceprofile.go
+++ b/generated/ieee802.1pmapperserviceprofile.go
@@ -27,11 +27,11 @@
 
 // Ieee8021PMapperServiceProfileClassID is the 16-bit ID for the OMCI
 // Managed entity IEEE 802.1p mapper service profile
-const Ieee8021PMapperServiceProfileClassID ClassID = ClassID(130)
+const Ieee8021PMapperServiceProfileClassID = ClassID(130) // 0x0082
 
 var ieee8021pmapperserviceprofileBME *ManagedEntityDefinition
 
-// Ieee8021PMapperServiceProfile (class ID #130)
+// Ieee8021PMapperServiceProfile (Class ID: #130 / 0x0082)
 //	This ME associates the priorities of IEEE 802.1p [IEEE 802.1D] priority tagged frames with
 //	specific connections. This ME directs upstream traffic to the designated GEM ports. Downstream
 //	traffic arriving on any of the IEEE 802.1p mapper's GEM ports is directed to the mapper's root
@@ -48,12 +48,25 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Tp Pointer
+//			This attribute points to an instance of the associated TP.
+//
+//			If the optional TP type attribute is not supported, the TP pointer indicates bridging mapping
+//			with the value 0xFFFF; the TP pointer may also point to a PPTP Ethernet UNI.
+//
+//			The TP type value 0 also indicates bridging mapping, and the TP pointer should be set to 0xFFFF.
+//
+//			In all other cases, the TP type is determined by the TP type attribute.
+//
 //			(R,-W, setbycreate) (mandatory) (2-bytes)
 //
+//			Each of the following eight attributes points to the GEM IW TP associated with the stated P-bit
+//			value. The null pointer 0xFFFF specifies that frames with the associated priority are to be
+//			discarded.
+//
 //		Interwork Tp Pointer For P_Bit Priority 0
 //			Interwork TP pointer for P-bit priority 0:	(R,-W, setbycreate) (mandatory) (2-bytes)
 //
@@ -79,6 +92,16 @@
 //			Interwork TP pointer for P-bit priority 7:	(R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Unmarked Frame Option
+//			This attribute specifies how the ONU should handle untagged Ethernet frames received across the
+//			associated interface. Although it does not alter the frame in any way, the ONU routes the frame
+//			as if it were tagged with P bits (PCP field) according to the following code points.
+//
+//			0	Derive implied PCP field from DSCP bits of received frame
+//
+//			1	Set implied PCP field to a fixed value specified by the default P-bit assumption attribute
+//
+//			(R,-W, setbycreate) (mandatory) (1-byte)
+//
 //			Untagged downstream frames are passed through the mapper transparently.
 //
 //		Dscp To P Bit Mapping
@@ -88,6 +111,13 @@
 //			adopt the priority mechanism based on IP precedence, which needs only the three MSBs of the DSCP
 //			field.
 //
+//			DSCP to P-bit mapping: This attribute is valid when the unmarked frame option attribute is set
+//			to 0. The DSCP to P-bit attribute can be considered a bit string sequence of 64 3-bit groupings.
+//			The 64 sequence entries represent the possible values of the 6-bit DSCP field. Each 3-bit
+//			grouping specifies the P-bit value to which the associated DSCP value should be mapped. The
+//			unmarked frame is then directed to the GEM IW TP indicated by the interwork TP pointer mappings.
+//			(R,-W) (mandatory) (24-bytes)
+//
 //		Default P Bit Assumption
 //			Default P-bit assumption: This attribute is valid when the unmarked frame option attribute is
 //			set to 1. In its LSBs, the default Pbit assumption attribute contains the default PCP field to
@@ -95,6 +125,28 @@
 //			pointer mappings. (R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Tp Type
+//			This attribute identifies the type of TP associated with the mapper.
+//
+//			0	Mapper used for bridging-mapping
+//
+//			1	Mapper directly associated with a PPTP Ethernet UNI
+//
+//			2	Mapper directly associated with an IP host config data or IPv6 host config data ME
+//
+//			3	Mapper directly associated with an Ethernet flow termination point
+//
+//			4	Mapper directly associated with a PPTP xDSL UNI
+//
+//			5	Reserved
+//
+//			6	Mapper directly associated with a PPTP MoCA UNI
+//
+//			7	Mapper directly associated with a virtual Ethernet interface point
+//
+//			8	Mapper directly associated with an IW VCC termination point
+//
+//			9	Mapper directly associated with an EFM bonding group
+//
 //			(R,-W, setbycreate) (optional) (1-byte)
 //
 type Ieee8021PMapperServiceProfile struct {
diff --git a/generated/interworkingvccterminationpoint.go b/generated/interworkingvccterminationpoint.go
index 9bffbde..0b1e18a 100644
--- a/generated/interworkingvccterminationpoint.go
+++ b/generated/interworkingvccterminationpoint.go
@@ -27,11 +27,11 @@
 
 // InterworkingVccTerminationPointClassID is the 16-bit ID for the OMCI
 // Managed entity Interworking VCC termination point
-const InterworkingVccTerminationPointClassID ClassID = ClassID(14)
+const InterworkingVccTerminationPointClassID = ClassID(14) // 0x000e
 
 var interworkingvccterminationpointBME *ManagedEntityDefinition
 
-// InterworkingVccTerminationPoint (class ID #14)
+// InterworkingVccTerminationPoint (Class ID: #14 / 0x000e)
 //	An instance of this ME represents a point in the ONU where the IW of a service or underlying
 //	physical infrastructure (e.g., ADSL) to an ATM layer takes place. At this point, ATM cells are
 //	generated from a bit stream (e.g., Ethernet) or a bit stream is reconstructed from ATM cells.
@@ -44,40 +44,52 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R,-setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. (R,-setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Vci Value
-//			VCI value:	This attribute identifies the VCI value associated with this IW VCC TP. (R,-W,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute identifies the VCI value associated with this IW VCC TP. (R,-W, setbycreate)
+//			(mandatory) (2-bytes)
 //
 //		Vp Network Ctp Connectivity Pointer
-//			VP network CTP connectivity pointer: This attribute points to the VP network CTP associated with
-//			this IW VCC TP. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute points to the VP network CTP associated with this IW VCC TP. (R,-W, setbycreate)
+//			(mandatory) (2-bytes)
 //
 //		Deprecated 1
-//			Deprecated 1: Not used; should be set to 0. (R,-W, setbycreate) (mandatory) (1-byte)
+//			Not used; should be set to 0. (R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Deprecated 2
-//			Deprecated 2: Not used; should be set to 0. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			Not used; should be set to 0. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Aal5 Profile Pointer
-//			AAL5 profile pointer: This attribute points to an instance of the AAL5 profile. (R,-W,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute points to an instance of the AAL5 profile. (R,-W, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Deprecated 3
-//			Deprecated 3: Not used; should be set to 0. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			Not used; should be set to 0. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Aal Loopback Configuration
+//			This attribute sets the ATM loopback configuration. All code points are retained for backward
+//			compatibility, but some are not expected to be needed in current and future applications.
+//
+//			0	No loopback
+//
+//			1	Loopback 1, loopback of downstream traffic before FEC of AAL1
+//
+//			2	Loopback 2, loopback of downstream traffic after FEC of AAL1
+//
+//			3	Loopback after AAL, loopback of downstream traffic after any AAL. Loopback after AAL is
+//			depicted in Figure 9.13.4-1.
+//
 //			The default value of this attribute is 0. (R,-W) (mandatory) (1-byte)
 //
 //		Pptp Counter
-//			PPTP counter: This value is the number of instances of PPTP MEs associated with this instance of
-//			the IW VCC TP. (R) (optional) (1-byte)
+//			This value is the number of instances of PPTP MEs associated with this instance of the IW VCC
+//			TP. (R) (optional) (1-byte)
 //
 //		Operational State
-//			Operational state: This attribute indicates whether the ME is capable of performing its
-//			function. Valid values are enabled (0) and disabled (1). (R) (optional) (1-byte)
+//			This attribute indicates whether the ME is capable of performing its function. Valid values are
+//			enabled (0) and disabled (1). (R) (optional) (1-byte)
 //
 type InterworkingVccTerminationPoint struct {
 	ManagedEntityDefinition
diff --git a/generated/iphostconfigdata.go b/generated/iphostconfigdata.go
index be0f1cc..5d5dcb1 100644
--- a/generated/iphostconfigdata.go
+++ b/generated/iphostconfigdata.go
@@ -27,11 +27,11 @@
 
 // IpHostConfigDataClassID is the 16-bit ID for the OMCI
 // Managed entity IP host config data
-const IpHostConfigDataClassID ClassID = ClassID(134)
+const IpHostConfigDataClassID = ClassID(134) // 0x0086
 
 var iphostconfigdataBME *ManagedEntityDefinition
 
-// IpHostConfigData (class ID #134)
+// IpHostConfigData (Class ID: #134 / 0x0086)
 //	The IP host config data configures IPv4 based services offered on the ONU. The ONU automatically
 //	creates instances of this ME if IP host services are available. A possible IPv6 stack is
 //	supported through the IPv6 host config data ME. In this clause, references to IP addresses are
@@ -44,72 +44,153 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The ONU creates
-//			as many instances as there are independent IPv4 stacks on the ONU. To facilitate discovery, IP
-//			host config data MEs should be numbered from 0 upwards. The ONU should create IP(v4) and IPv6
-//			host config data MEs with separate ME IDs, such that other MEs can use a single TP type
-//			attribute to link with either. (R) (mandatory) (2 bytes)
+//			This attribute uniquely identifies each instance of this ME. The ONU creates as many instances
+//			as there are independent IPv4 stacks on the ONU. To facilitate discovery, IP host config data
+//			MEs should be numbered from 0 upwards. The ONU should create IP(v4) and IPv6 host config data
+//			MEs with separate ME IDs, such that other MEs can use a single TP type attribute to link with
+//			either. (R) (mandatory) (2 bytes)
 //
 //		Ip Options
+//			This attribute is a bit map that enables or disables IP-related options. The value 1 enables the
+//			option while 0 disables it. The default value of this attribute is 0.
+//
+//			0x01	Enable DHCP
+//
+//			0x02	Respond to pings
+//
+//			0x04	Respond to traceroute messages
+//
+//			0x08	Enable IP stack
+//
+//			0x10..0x80	Reserved
+//
 //			(R,-W) (mandatory) (1-byte)
 //
 //		Mac Address
-//			MAC address: This attribute indicates the MAC address used by the IP node. (R) (mandatory)
-//			(6-bytes)
+//			This attribute indicates the MAC address used by the IP node. (R) (mandatory) (6-bytes)
 //
 //		Onu Identifier
-//			Onu identifier: A unique ONU identifier string. If set to a non-null value, this string is used
-//			instead of the MAC address in retrieving dynamic host configuration protocol (DHCP) parameters.
-//			If the string is shorter than 25 characters, it must be null terminated. Its default value is 25
-//			null bytes. (R,-W) (mandatory) (25-bytes)
+//			A unique ONU identifier string. If set to a non-null value, this string is used instead of the
+//			MAC address in retrieving dynamic host configuration protocol (DHCP) parameters. If the string
+//			is shorter than 25 characters, it must be null terminated. Its default value is 25 null bytes.
+//			(R,-W) (mandatory) (25-bytes)
+//
+//			Several attributes of this ME may be paired together into two categories, manual settings and
+//			current values.
+//
+//			While the IP stack is disabled, there is no IP connectivity to the external world from this ME
+//			instance.
+//
+//			While DHCP is disabled, the current values are always the same as the manual settings. While
+//			DHCP is enabled, the current values are those assigned by DHCP, or undefined (0) if DHCP has
+//			never assigned values.
 //
 //		Ip Address
-//			IP address:	The address used for IP host services; this attribute has the default value 0.
-//			(R,-W) (mandatory) (4-bytes)
-//
-//		Mask
-//			Mask:	The subnet mask for IP host services; this attribute has the default value 0. (R,-W)
+//			The address used for IP host services; this attribute has the default value 0. (R,-W)
 //			(mandatory) (4-bytes)
 //
-//		Gateway
-//			Gateway:	The default gateway address used for IP host services; this attribute has the default
-//			value 0. (R,-W) (mandatory) (4-bytes)
-//
-//		Primary Dns
-//			Primary DNS: The address of the primary DNS server; this attribute has the default value 0.
-//			(R,-W) (mandatory) (4-bytes)
-//
-//		Secondary Dns
-//			Secondary DNS: The address of the secondary DNS server; this attribute has the default value 0.
-//			(R,-W) (mandatory) (4-bytes)
-//
-//		Current Address
-//			Current address: Current address of the IP host service. (R) (optional) (4-bytes)
-//
-//		Current Mask
-//			Current mask: Current subnet mask for the IP host service. (R) (optional) (4-bytes)
-//
-//		Current Gateway
-//			Current gateway: Current default gateway address for the IP host service. (R) (optional)
+//		Mask
+//			The subnet mask for IP host services; this attribute has the default value 0. (R,-W) (mandatory)
 //			(4-bytes)
 //
+//		Gateway
+//			The default gateway address used for IP host services; this attribute has the default value 0.
+//			(R,-W) (mandatory) (4-bytes)
+//
+//		Primary Dns
+//			The address of the primary DNS server; this attribute has the default value 0. (R,-W)
+//			(mandatory) (4-bytes)
+//
+//		Secondary Dns
+//			The address of the secondary DNS server; this attribute has the default value 0. (R,-W)
+//			(mandatory) (4-bytes)
+//
+//		Current Address
+//			Current address of the IP host service. (R) (optional) (4-bytes)
+//
+//		Current Mask
+//			Current subnet mask for the IP host service. (R) (optional) (4-bytes)
+//
+//		Current Gateway
+//			Current default gateway address for the IP host service. (R) (optional) (4-bytes)
+//
 //		Current Primary Dns
-//			Current primary DNS: Current primary DNS server address. (R) (optional) (4-bytes)
+//			Current primary DNS server address. (R) (optional) (4-bytes)
 //
 //		Current Secondary Dns
-//			Current secondary DNS: Current secondary DNS server address. (R) (optional) (4-bytes)
+//			Current secondary DNS server address. (R) (optional) (4-bytes)
 //
 //		Domain Name
-//			Domain name: If DHCP indicates a domain name, it is presented here. If no domain name is
-//			indicated, this attribute is set to a null string. If the string is shorter than 25-bytes, it
-//			must be null terminated. The default value is 25 null bytes. (R) (mandatory) (25-bytes)
+//			If DHCP indicates a domain name, it is presented here. If no domain name is indicated, this
+//			attribute is set to a null string. If the string is shorter than 25-bytes, it must be null
+//			terminated. The default value is 25 null bytes. (R) (mandatory) (25-bytes)
 //
 //		Host Name
-//			Host name:	If DHCP indicates a host name, it is presented here. If no host name is indicated,
-//			this attribute is set to a null string. If the string is shorter than 25-bytes, it must be null
+//			If DHCP indicates a host name, it is presented here. If no host name is indicated, this
+//			attribute is set to a null string. If the string is shorter than 25-bytes, it must be null
 //			terminated. The default value is 25 null bytes. (R) (mandatory) (25-bytes)
 //
 //		Relay Agent Options
+//			This attribute is a pointer to a large string ME whose content specifies one or more DHCP relay
+//			agent options. (R, W) (optional) (2-bytes)
+//
+//			The contents of the large string are parsed by the ONU and converted into text strings. Variable
+//			substitution is based on defined three-character groups, each of which begins with the '%'
+//			character. The string '%%' is an escape mechanism whose output is a single '%' character. When
+//			the ONU cannot perform variable substitution on a substring of the large string, it generates
+//			the specified option as an exact quotation of the provisioned substring value.
+//
+//			Provisioning of the large string is separate from the operation of setting the pointer in this
+//			attribute. It is the responsibility of the OLT to ensure that the large string contents are
+//			correct and meaningful.
+//
+//			Three-character variable definitions are as follows. The first variable in the large string must
+//			specify one of the option types. Both options for a given IP version may be present if desired,
+//			each introduced by its option identifier. Terminology is taken from clause 3.9.3 of [b-BBF
+//			TR-101].
+//
+//			%01, %18 Specifies that the following string is for option 82 sub-option 1, agent circuit-ID
+//			(IPv4) or option 18, interface-ID (IPv6). The equivalence permits the same large string to be
+//			used in both IP environments.
+//
+//			%02, %37 Specifies that the following string is for option 82 sub-option 2, relay agent remote-
+//			ID (IPv4) or option 37, relay agent remote-ID (IPv6). The equivalence permits the same large
+//			string to be used in both IP environments.
+//
+//			%SL	In [b-BBF TR-101], this is called a slot. In an ONU, this variable refers to a shelf. It
+//			would be meaningful if the ONU has multiple shelves internally or is daisy-chained to multiple
+//			equipment modules. The range of this variable is "0".. "99"
+//
+//			%SU	In TR-101, this is called a sub-slot. In fact, it represents a cardholder. The range of this
+//			variable is "0".. "99"
+//
+//			%PO	UNI port number. The range of this variable is "0".. "999"
+//
+//			%AE	ATM or Ethernet. This variable can take on the values "atm" or "eth".
+//
+//			%SV	S-VID for Ethernet UNI, or ATM virtual path identifier (VPI) for ATM UNI, as it exists on
+//			the DHCP request received upstream across the UNI. Range "0".. "4096" for S-VID; range "0"..
+//			"255" for VPI. The value "4096" indicates no S-VID tag.
+//
+//			%CV	C-VID (Q-VID) for Ethernet UNI, or ATM virtual circuit identifier (VCI) for ATM UNI, as it
+//			exists on the DHCP request received upstream across the UNI. Range "0".. "4096" for C-VID; range
+//			"0".."65535" for VCI. The value "4096" indicates no C-VID tag.
+//
+//			Spaces in the provisioned string are significant.
+//
+//			Example: if the large string were provisioned with the value
+//
+//			%01%SL/%SU/%PO:%AE/%SV.%CV<null>,
+//
+//			then the ONU would generate the following DHCP option 82 agent circuit-ID string for an Ethernet
+//			UNI that sent a DHCP request with no S tag and C tag = 3210 on shelf 2, slot 3, port 4.
+//
+//			2/3/4:eth/4096.3210
+//
+//			With the same provisioning, the ONU would generate the following DHCP option 82 agent circuit-ID
+//			string for an ATM UNI that sent a DHCP request on VPI = 123 and VCI = 4567 on shelf 2, slot 3,
+//			port 4.
+//
 //			2/3/4:atm/123.4567
 //
 type IpHostConfigData struct {
diff --git a/generated/iphostperformancemonitoringhistorydata.go b/generated/iphostperformancemonitoringhistorydata.go
index 75d6f68..0622bf5 100644
--- a/generated/iphostperformancemonitoringhistorydata.go
+++ b/generated/iphostperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // IpHostPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity IP host performance monitoring history data
-const IpHostPerformanceMonitoringHistoryDataClassID ClassID = ClassID(135)
+const IpHostPerformanceMonitoringHistoryDataClassID = ClassID(135) // 0x0087
 
 var iphostperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// IpHostPerformanceMonitoringHistoryData (class ID #135)
+// IpHostPerformanceMonitoringHistoryData (Class ID: #135 / 0x0087)
 //	This ME collects PM data related to an IP host. Instances of this ME are created and deleted by
 //	the OLT.
 //
@@ -43,13 +43,12 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the IP host configuration data or
-//			IPv6 host configuration data ME. (R, set-by-create) (mandatory) (2 bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the IP host configuration data or IPv6 host configuration
+//			data ME. (R, set-by-create) (mandatory) (2 bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -57,26 +56,26 @@
 //			data 2 ME is optional. (R,-W, set-by-create) (mandatory) (2-bytes)
 //
 //		Icmp Errors
-//			ICMP errors: This attribute counts ICMP errors received. (R) (mandatory) (4-bytes)
+//			This attribute counts ICMP errors received. (R) (mandatory) (4-bytes)
 //
 //		Dns Errors
-//			DNS errors:	This attribute counts DNS errors received. (R) (mandatory) (4-bytes)
+//			This attribute counts DNS errors received. (R) (mandatory) (4-bytes)
 //
 //		Dhcp Timeouts
-//			DHCP timeouts:	This attribute counts DHCP timeouts. (R) (optional) (2 bytes)
+//			This attribute counts DHCP timeouts. (R) (optional) (2 bytes)
 //
 //		Ip Address Conflict
-//			IP address conflict: This attribute is incremented whenever the ONU detects a conflicting IP
-//			address on the network. A conflicting IP address is one that has the same value as the one
-//			currently assigned to the ONU. (R) (optional) (2 bytes)
+//			This attribute is incremented whenever the ONU detects a conflicting IP address on the network.
+//			A conflicting IP address is one that has the same value as the one currently assigned to the
+//			ONU. (R) (optional) (2 bytes)
 //
 //		Out Of Memory
-//			Out of memory: This attribute is incremented whenever the ONU encounters an out of memory
-//			condition in the IP stack. (R) (optional) (2 bytes)
+//			This attribute is incremented whenever the ONU encounters an out of memory condition in the IP
+//			stack. (R) (optional) (2 bytes)
 //
 //		Internal Error
-//			Internal error: This attribute is incremented whenever the ONU encounters an internal error
-//			condition such as a driver interface failure in the IP stack. (R) (optional) (2-bytes)
+//			This attribute is incremented whenever the ONU encounters an internal error condition such as a
+//			driver interface failure in the IP stack. (R) (optional) (2-bytes)
 //
 type IpHostPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/largestring.go b/generated/largestring.go
new file mode 100644
index 0000000..668ec03
--- /dev/null
+++ b/generated/largestring.go
@@ -0,0 +1,171 @@
+/*
+ * 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.
+ */
+/*
+ * NOTE: This file was generated, manual edits will be overwritten!
+ *
+ * Generated by 'goCodeGenerator.py':
+ *              https://github.com/cboling/OMCI-parser/README.md
+ */
+
+package generated
+
+import "github.com/deckarep/golang-set"
+
+// LargeStringClassID is the 16-bit ID for the OMCI
+// Managed entity Large string
+const LargeStringClassID = ClassID(157) // 0x009d
+
+var largestringBME *ManagedEntityDefinition
+
+// LargeString (Class ID: #157 / 0x009d)
+//	The large string ME holds character strings longer than 25-bytes, up to 375-bytes. It is
+//	maintained in up to 15 parts, each part containing 25-bytes. If the final part contains fewer
+//	than 25-bytes, it is terminated by at least one null byte. For example:
+//
+//	Or
+//
+//	Instances of this ME are created and deleted by the OLT. Under some circumstances, they may also
+//	be created by the ONU. To use this ME, the OLT or ONU instantiates the large string ME and then
+//	points to the created ME from other ME instances. Systems that maintain the large string should
+//	ensure that the large string ME is not deleted while it is still linked.
+//
+//	Relationships
+//		An instance of this ME may be cited by any ME that requires a text string longer than 25-bytes.
+//
+//	Attributes
+//		Managed Entity Id
+//			This attribute uniquely identifies each instance of this ME. The value 0xFFFF is reserved. When
+//			the large string is to be used as an IPv6 address, the value 0 is also reserved. The OLT should
+//			create large string MEs starting at 1 (or 0), and numbering upwards. The ONU should create large
+//			string MEs starting at 65534 (0xFFFE) and numbering downwards. (R,-setbycreate) (mandatory)
+//			(2-bytes)
+//
+//		Number Of Parts
+//			This attribute specifies the number of non-empty parts that form the large string. This
+//			attribute defaults to 0 to indicate no large string content is defined.(R,-W) (mandatory)
+//			(1-byte)
+//
+//			Fifteen additional attributes are defined in the following; they are identical. The large string
+//			is simply divided into as many parts as necessary, starting at part 1. If the end of the string
+//			does not lie at a part boundary, it is marked with a null byte.
+//
+//		Part 1
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15: (R,-W) (mandatory) (25-bytes * 15 attributes)
+//
+//		Part 2
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15: (R,-W) (mandatory) (25-bytes * 15 attributes)
+//
+//		Part 3
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15: (R,-W) (mandatory) (25-bytes * 15 attributes)
+//
+//		Part 4
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15: (R,-W) (mandatory) (25-bytes * 15 attributes)
+//
+//		Part 5
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15: (R,-W) (mandatory) (25-bytes * 15 attributes)
+//
+//		Part 6
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15: (R,-W) (mandatory) (25-bytes * 15 attributes)
+//
+//		Part 7
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15: (R,-W) (mandatory) (25-bytes * 15 attributes)
+//
+//		Part 8
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15: (R,-W) (mandatory) (25-bytes * 15 attributes)
+//
+//		Part 9
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15: (R,-W) (mandatory) (25-bytes * 15 attributes)
+//
+//		Part 10
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15: (R,-W) (mandatory) (25-bytes * 15 attributes)
+//
+//		Part 11
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15: (R,-W) (mandatory) (25-bytes * 15 attributes)
+//
+//		Part 12
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15: (R,-W) (mandatory) (25-bytes * 15 attributes)
+//
+//		Part 13
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15: (R,-W) (mandatory) (25-bytes * 15 attributes)
+//
+//		Part 14
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15: (R,-W) (mandatory) (25-bytes * 15 attributes)
+//
+//		Part 15
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15: (R,-W) (mandatory) (25-bytes * 15 attributes)
+//
+type LargeString struct {
+	ManagedEntityDefinition
+	Attributes AttributeValueMap
+}
+
+func init() {
+	largestringBME = &ManagedEntityDefinition{
+		Name:    "LargeString",
+		ClassID: 157,
+		MessageTypes: mapset.NewSetWith(
+			Create,
+			Delete,
+			Get,
+			Set,
+		),
+		AllowedAttributeMask: 0xffff,
+		AttributeDefinitions: AttributeDefinitionMap{
+			0:  Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read, SetByCreate), false, false, false, 0),
+			1:  ByteField("NumberOfParts", UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read, Write), true, false, false, 1),
+			2:  MultiByteField("Part1", OctetsAttributeType, 0x4000, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), true, false, false, 2),
+			3:  MultiByteField("Part2", OctetsAttributeType, 0x2000, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), true, false, false, 3),
+			4:  MultiByteField("Part3", OctetsAttributeType, 0x1000, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), true, false, false, 4),
+			5:  MultiByteField("Part4", OctetsAttributeType, 0x0800, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), true, false, false, 5),
+			6:  MultiByteField("Part5", OctetsAttributeType, 0x0400, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), true, false, false, 6),
+			7:  MultiByteField("Part6", OctetsAttributeType, 0x0200, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), true, false, false, 7),
+			8:  MultiByteField("Part7", OctetsAttributeType, 0x0100, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), true, false, false, 8),
+			9:  MultiByteField("Part8", OctetsAttributeType, 0x0080, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), true, false, false, 9),
+			10: MultiByteField("Part9", OctetsAttributeType, 0x0040, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), true, false, false, 10),
+			11: MultiByteField("Part10", OctetsAttributeType, 0x0020, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), true, false, false, 11),
+			12: MultiByteField("Part11", OctetsAttributeType, 0x0010, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), true, false, false, 12),
+			13: MultiByteField("Part12", OctetsAttributeType, 0x0008, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), true, false, false, 13),
+			14: MultiByteField("Part13", OctetsAttributeType, 0x0004, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), true, false, false, 14),
+			15: MultiByteField("Part14", OctetsAttributeType, 0x0002, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), true, false, false, 15),
+			16: MultiByteField("Part15", OctetsAttributeType, 0x0001, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), true, false, false, 16),
+		},
+		Access:  CreatedByOlt,
+		Support: UnknownSupport,
+	}
+}
+
+// NewLargeString (class ID 157) creates the basic
+// Managed Entity definition that is used to validate an ME of this type that
+// is received from or transmitted to the OMCC.
+func NewLargeString(params ...ParamData) (*ManagedEntity, OmciErrors) {
+	return NewManagedEntity(*largestringBME, params...)
+}
diff --git a/generated/macbridgeconfigurationdata.go b/generated/macbridgeconfigurationdata.go
index 8718214..0431803 100644
--- a/generated/macbridgeconfigurationdata.go
+++ b/generated/macbridgeconfigurationdata.go
@@ -27,11 +27,11 @@
 
 // MacBridgeConfigurationDataClassID is the 16-bit ID for the OMCI
 // Managed entity MAC bridge configuration data
-const MacBridgeConfigurationDataClassID ClassID = ClassID(46)
+const MacBridgeConfigurationDataClassID = ClassID(46) // 0x002e
 
 var macbridgeconfigurationdataBME *ManagedEntityDefinition
 
-// MacBridgeConfigurationData (class ID #46)
+// MacBridgeConfigurationData (Class ID: #46 / 0x002e)
 //	This ME organizes status data associated with a MAC bridge. The ONU automatically creates or
 //	deletes an instance of this ME upon the creation or deletion of a MAC bridge service profile.
 //
@@ -40,45 +40,46 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the MAC bridge service profile. (R)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the MAC bridge service profile. (R) (mandatory) (2-bytes)
 //
 //		Bridge Mac Address
-//			Bridge MAC address: This attribute indicates the MAC address used by the bridge. The ONU sets
-//			this attribute to a value based on criteria beyond the scope of this Recommendation, e.g.,
-//			factory settings. (R) (mandatory) (6-bytes)
+//			This attribute indicates the MAC address used by the bridge. The ONU sets this attribute to a
+//			value based on criteria beyond the scope of this Recommendation, e.g., factory settings. (R)
+//			(mandatory) (6-bytes)
 //
 //		Bridge Priority
-//			Bridge priority: This attribute reports the priority of the bridge. The ONU copies this
-//			attribute from the priority attribute of the associated MAC bridge service profile. The value of
-//			this attribute changes with updates to the MAC bridge service profile priority attribute. (R)
-//			(mandatory) (2-bytes)
+//			This attribute reports the priority of the bridge. The ONU copies this attribute from the
+//			priority attribute of the associated MAC bridge service profile. The value of this attribute
+//			changes with updates to the MAC bridge service profile priority attribute. (R) (mandatory)
+//			(2-bytes)
 //
 //		Designated Root
-//			Designated root: This attribute identifies the bridge at the root of the spanning tree. It
-//			comprises bridge priority (2-bytes) and MAC address (6-bytes). (R) (mandatory) (8-bytes)
+//			This attribute identifies the bridge at the root of the spanning tree. It comprises bridge
+//			priority (2-bytes) and MAC address (6-bytes). (R) (mandatory) (8-bytes)
 //
 //		Root Path Cost
-//			Root path cost: This attribute reports the cost of the best path to the root as seen from this
-//			bridge. Upon ME instantiation, the ONU sets this attribute to 0. (R) (mandatory) (4-bytes)
+//			This attribute reports the cost of the best path to the root as seen from this bridge. Upon ME
+//			instantiation, the ONU sets this attribute to 0. (R) (mandatory) (4-bytes)
 //
 //		Bridge Port Count
-//			Bridge port count: This attribute records the number of ports linked to this bridge. (R)
-//			(mandatory) (1-byte)
+//			This attribute records the number of ports linked to this bridge. (R) (mandatory) (1-byte)
 //
 //		Root Port Num
-//			Root port num: This attribute contains the port number that has the lowest cost from the bridge
-//			to the root bridge. The value 0 means that this bridge is itself the root. Upon ME
-//			instantiation, the ONU sets this attribute to 0. (R) (mandatory) (2-bytes)
+//			This attribute contains the port number that has the lowest cost from the bridge to the root
+//			bridge. The value 0 means that this bridge is itself the root. Upon ME instantiation, the ONU
+//			sets this attribute to 0. (R) (mandatory) (2-bytes)
 //
 //		Hello Time
 //			NOTE - [IEEE 802.1D] specifies the compatibility range for hello time to be 1..2-s.
 //
+//			This attribute is the hello time received from the designated root, the interval (in 256ths of a
+//			second) between HELLO packets. Its range is 0x0100 to 0x0A00 (1..10-s). (R) (optional) (2-bytes)
+//
 //		Forward Delay
-//			Forward delay: This attribute is the forwarding delay time received from the designated root (in
-//			256ths of a second). Its range is 0x0400 to 0x1E00 (4..30-s) in accordance with [IEEE 802.1D].
-//			(R) (optional) (2-bytes)
+//			This attribute is the forwarding delay time received from the designated root (in 256ths of a
+//			second). Its range is 0x0400 to 0x1E00 (4..30-s) in accordance with [IEEE 802.1D]. (R)
+//			(optional) (2-bytes)
 //
 type MacBridgeConfigurationData struct {
 	ManagedEntityDefinition
diff --git a/generated/macbridgeperformancemonitoringhistorydata.go b/generated/macbridgeperformancemonitoringhistorydata.go
index 19de76b..c80f91f 100644
--- a/generated/macbridgeperformancemonitoringhistorydata.go
+++ b/generated/macbridgeperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // MacBridgePerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity MAC bridge performance monitoring history data
-const MacBridgePerformanceMonitoringHistoryDataClassID ClassID = ClassID(51)
+const MacBridgePerformanceMonitoringHistoryDataClassID = ClassID(51) // 0x0033
 
 var macbridgeperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// MacBridgePerformanceMonitoringHistoryData (class ID #51)
+// MacBridgePerformanceMonitoringHistoryData (Class ID: #51 / 0x0033)
 //	This ME collects PM data associated with a MAC bridge. Instances of this ME are created and
 //	deleted by the OLT.
 //
@@ -42,13 +42,12 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the MAC bridge service profile. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the MAC bridge service profile. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -57,11 +56,10 @@
 //			ME is optional. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Bridge Learning Entry Discard Count
-//			Bridge learning entry discard count: This attribute counts forwarding database entries that have
-//			been or would have been learned, but were discarded or replaced due to a lack of space in the
-//			database table. When used with the MAC learning depth attribute of the MAC bridge service
-//			profile, the bridge learning entry discard count may be particularly useful in detecting MAC
-//			spoofing attempts. (R) (mandatory) (4-bytes)
+//			This attribute counts forwarding database entries that have been or would have been learned, but
+//			were discarded or replaced due to a lack of space in the database table. When used with the MAC
+//			learning depth attribute of the MAC bridge service profile, the bridge learning entry discard
+//			count may be particularly useful in detecting MAC spoofing attempts. (R) (mandatory) (4-bytes)
 //
 type MacBridgePerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/macbridgeportbridgetabledata.go b/generated/macbridgeportbridgetabledata.go
index 1263f0c..50e8610 100644
--- a/generated/macbridgeportbridgetabledata.go
+++ b/generated/macbridgeportbridgetabledata.go
@@ -27,11 +27,11 @@
 
 // MacBridgePortBridgeTableDataClassID is the 16-bit ID for the OMCI
 // Managed entity MAC bridge port bridge table data
-const MacBridgePortBridgeTableDataClassID ClassID = ClassID(50)
+const MacBridgePortBridgeTableDataClassID = ClassID(50) // 0x0032
 
 var macbridgeportbridgetabledataBME *ManagedEntityDefinition
 
-// MacBridgePortBridgeTableData (class ID #50)
+// MacBridgePortBridgeTableData (Class ID: #50 / 0x0032)
 //	This ME reports status data associated with a bridge port. The ONU automatically creates or
 //	deletes an instance of this ME upon the creation or deletion of a MAC bridge port configuration
 //	data.
@@ -42,11 +42,36 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the MAC bridge port configuration
-//			data ME. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the MAC bridge port configuration data ME. (R) (mandatory)
+//			(2-bytes)
 //
 //		Bridge Table
+//			This attribute lists known MAC DAs, whether they are learned or statically assigned, whether
+//			packets that have them as DAs are filtered or forwarded, and their ages. Each entry contains:
+//
+//			-	Information (2-bytes);
+//
+//			-	MAC address (6-bytes).
+//
+//			The information bits are assigned as described as follows.
+//
+//			Bit	Name	Setting
+//
+//			1 (LSB)	Filter/forward	0: forward
+//
+//			1: filter
+//
+//			2	Reserved	0
+//
+//			3	Dynamic/static	0: this entry is statically assigned
+//
+//			1: this entry is dynamically learned
+//
+//			4	Reserved	0
+//
+//			16..5	Age	Age in seconds (1..4095)
+//
 //			Upon ME instantiation, this attribute is an empty list. (R) (mandatory) (8-*-M-bytes, where M is
 //			the number of entries in the list.)
 //
diff --git a/generated/macbridgeportconfigurationdata.go b/generated/macbridgeportconfigurationdata.go
index 092986f..24e245d 100644
--- a/generated/macbridgeportconfigurationdata.go
+++ b/generated/macbridgeportconfigurationdata.go
@@ -27,11 +27,11 @@
 
 // MacBridgePortConfigurationDataClassID is the 16-bit ID for the OMCI
 // Managed entity MAC bridge port configuration data
-const MacBridgePortConfigurationDataClassID ClassID = ClassID(47)
+const MacBridgePortConfigurationDataClassID = ClassID(47) // 0x002f
 
 var macbridgeportconfigurationdataBME *ManagedEntityDefinition
 
-// MacBridgePortConfigurationData (class ID #47)
+// MacBridgePortConfigurationData (Class ID: #47 / 0x002f)
 //	This ME models a port on a MAC bridge. Instances of this ME are created and deleted by the OLT.
 //
 //	Relationships
@@ -40,63 +40,100 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Bridge Id Pointer
-//			Bridge ID pointer: This attribute points to an instance of the MAC bridge service profile.
-//			(R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute points to an instance of the MAC bridge service profile. (R,-W, setbycreate)
+//			(mandatory) (2-bytes)
 //
 //		Port Num
-//			Port num:	This attribute is the bridge port number. It must be unique among all ports associated
-//			with a particular MAC bridge service profile. (R,-W, setbycreate) (mandatory) (1-byte)
+//			This attribute is the bridge port number. It must be unique among all ports associated with a
+//			particular MAC bridge service profile. (R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Tp Type
+//			This attribute identifies the type of TP associated with this MAC bridge port. Valid values are
+//			as follows.
+//
+//			1	Physical path termination point Ethernet UNI
+//
+//			2	Interworking virtual circuit connection (VCC) termination point
+//
+//			3	IEEE 802.1p mapper service profile
+//
+//			4	IP host config data or IPv6 host config data
+//
+//			5	GEM interworking termination point
+//
+//			6	Multicast GEM interworking termination point
+//
+//			7	Physical path termination point xDSL UNI part 1
+//
+//			8	Physical path termination point VDSL UNI
+//
+//			9	Ethernet flow termination point
+//
+//			10	Reserved
+//
+//			11	Virtual Ethernet interface point
+//
+//			12	Physical path termination point MoCA UNI
+//
+//			13	Ethernet in the first mile (EFM) bonding group
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Tp Pointer
 //			NOTE 1 - When the TP type is very high-speed digital subscriber line (VDSL) or xDSL, the two
 //			MSBs may be used to indicate a bearer channel.
 //
+//			This attribute points to the TP associated with this MAC bridge port. The TP type attribute
+//			indicates the type of the TP; this attribute contains its instance identifier (ME ID). (R,-W,
+//			setbycreate) (mandatory) (2-bytes)
+//
 //		Port Priority
-//			Port priority:	This attribute denotes the priority of the port for use in (rapid) spanning tree
-//			algorithms. The range is 0..255. (R,-W, setbycreate) (optional) (2-bytes)
+//			This attribute denotes the priority of the port for use in (rapid) spanning tree algorithms. The
+//			range is 0..255. (R,-W, setbycreate) (optional) (2-bytes)
 //
 //		Port Path Cost
-//			Port path cost: This attribute specifies the contribution of the port to the path cost towards
-//			the spanning tree root bridge. The range is 1..65535. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute specifies the contribution of the port to the path cost towards the spanning tree
+//			root bridge. The range is 1..65535. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Port Spanning Tree Ind
-//			Port spanning tree ind: The Boolean value true enables (R)STP LAN topology change detection at
-//			this port. The value false disables topology change detection. (R,-W, setbycreate) (mandatory)
-//			(1-byte)
+//			The Boolean value true enables (R)STP LAN topology change detection at this port. The value
+//			false disables topology change detection. (R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Deprecated 1
-//			Deprecated 1: This attribute is not used. If present, it should be ignored by both the ONU and
-//			the OLT, except as necessary to comply with OMCI message definitions. (R,-W, setbycreate)
-//			(optional) (1-byte)
+//			This attribute is not used. If present, it should be ignored by both the ONU and the OLT, except
+//			as necessary to comply with OMCI message definitions. (R,-W, setbycreate) (optional) (1-byte)
 //
 //		Deprecated 2
-//			Deprecated 2: This attribute is not used. If present, it should be ignored by both the ONU and
-//			the OLT, except as necessary to comply with OMCI message definitions. (R,-W, setbycreate)
-//			(1-byte) (optional)
+//			This attribute is not used. If present, it should be ignored by both the ONU and the OLT, except
+//			as necessary to comply with OMCI message definitions. (R,-W, setbycreate) (1-byte) (optional)
 //
 //		Port Mac Address
-//			Port MAC address: If the TP associated with this port has a MAC address, this attribute
-//			specifies it. (R) (optional) (6-bytes)
+//			If the TP associated with this port has a MAC address, this attribute specifies it. (R)
+//			(optional) (6-bytes)
 //
 //		Outbound Td Pointer
-//			Outbound TD pointer: This attribute points to a traffic descriptor that limits the traffic rate
-//			leaving the MAC bridge. (R,-W) (optional) (2-byte)
+//			This attribute points to a traffic descriptor that limits the traffic rate leaving the MAC
+//			bridge. (R,-W) (optional) (2-byte)
 //
 //		Inbound Td Pointer
-//			Inbound TD pointer: This attribute points to a traffic descriptor that limits the traffic rate
-//			entering the MAC bridge. (R,-W) (optional) (2-byte)
+//			This attribute points to a traffic descriptor that limits the traffic rate entering the MAC
+//			bridge. (R,-W) (optional) (2-byte)
 //
 //		Mac Learning Depth
+//			This attribute specifies the maximum number of MAC addresses to be learned by this MAC bridge
+//			port. The default value 0 specifies that there is no administratively imposed limit. (R,-W,
+//			setbycreate) (optional) (1-byte)
+//
 //			NOTE 2 - If this attribute is not zero, its value overrides the value set in the MAC learning
 //			depth attribute of the MAC bridge service profile.
 //
+//		Lasp Id Pointer
+//			This attribute points to an instance of the LASP ME. (R,W, setbycreate) (optional) (2 bytes)
+//
 type MacBridgePortConfigurationData struct {
 	ManagedEntityDefinition
 	Attributes AttributeValueMap
@@ -112,7 +149,7 @@
 			Get,
 			Set,
 		),
-		AllowedAttributeMask: 0xfff8,
+		AllowedAttributeMask: 0xfffc,
 		AttributeDefinitions: AttributeDefinitionMap{
 			0:  Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read, SetByCreate), false, false, false, 0),
 			1:  Uint16Field("BridgeIdPointer", UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 1),
@@ -128,6 +165,7 @@
 			11: Uint16Field("OutboundTdPointer", PointerAttributeType, 0x0020, 0, mapset.NewSetWith(Read, Write), false, true, false, 11),
 			12: Uint16Field("InboundTdPointer", PointerAttributeType, 0x0010, 0, mapset.NewSetWith(Read, Write), false, true, false, 12),
 			13: ByteField("MacLearningDepth", UnsignedIntegerAttributeType, 0x0008, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, true, false, 13),
+			14: Uint16Field("LaspIdPointer", UnsignedIntegerAttributeType, 0x0004, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, true, false, 14),
 		},
 		Access:  CreatedByOlt,
 		Support: UnknownSupport,
diff --git a/generated/macbridgeportdesignationdata.go b/generated/macbridgeportdesignationdata.go
index e14230e..df0da16 100644
--- a/generated/macbridgeportdesignationdata.go
+++ b/generated/macbridgeportdesignationdata.go
@@ -27,11 +27,11 @@
 
 // MacBridgePortDesignationDataClassID is the 16-bit ID for the OMCI
 // Managed entity MAC bridge port designation data
-const MacBridgePortDesignationDataClassID ClassID = ClassID(48)
+const MacBridgePortDesignationDataClassID = ClassID(48) // 0x0030
 
 var macbridgeportdesignationdataBME *ManagedEntityDefinition
 
-// MacBridgePortDesignationData (class ID #48)
+// MacBridgePortDesignationData (Class ID: #48 / 0x0030)
 //	This ME records data associated with a bridge port. The ONU automatically creates or deletes an
 //	instance of this managed entity upon the creation or deletion of a MAC bridge port configuration
 //	data ME.
@@ -41,14 +41,51 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the MAC bridge port configuration
-//			data. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the MAC bridge port configuration data. (R) (mandatory)
+//			(2-bytes)
 //
 //		Designated Bridge Root Cost Port
+//			This attribute contains the designated root, designated cost, designated bridge and designated
+//			port, which are some of the outputs of the read port parameters operation defined in clause
+//			14.8.2.1 of [IEEE-802.1D]:
+//
+//			o	identifier of the designated bridge for the port's segment (8-bytes);
+//
+//			o	bridge identifier of the root transmitted by the designated bridge for the segment (8-bytes);
+//
+//			o	port number of the designated port on the designated bridge considered to be part of this
+//			port's segment (4-bytes);
+//
+//			o	path cost contribution of the designated port to this port's segment (4-bytes).
+//
 //			Upon ME instantiation, the ONU sets this attribute to 0. (R) (mandatory) (24-bytes)
 //
 //		Port State
+//			This attribute provides status information on the port. Valid values include the following.
+//
+//			0	Disabled
+//
+//			1	Listening
+//
+//			2	Learning
+//
+//			3	Forwarding
+//
+//			4	Blocking
+//
+//			5	Linkdown
+//
+//			6	(R)Stp_off
+//
+//			in accordance with [IEEE 802.1D]. (R) (mandatory) (1-byte)
+//
+//			NOTE - The value linkdown is introduced to denote the port status when the Ethernet link state
+//			is down. This value distinguishes the case where Ethernet is physically down from the case where
+//			Ethernet is administratively locked, the latter being denoted by disabled. Be aware that this
+//			terminology violates the ITUT convention that disabled is an operational state, not
+//			administrative.
+//
 //			The value (R)stp_off is introduced to denote the port status where the (rapid) spanning tree
 //			protocol has been disabled by setting the port spanning tree ind attribute of the MAC bridge
 //			port configuration data to false, and the Ethernet link state is up. This value distinguishes
diff --git a/generated/macbridgeportfilterpre-assigntable.go b/generated/macbridgeportfilterpre-assigntable.go
index 0912f1f..604af06 100644
--- a/generated/macbridgeportfilterpre-assigntable.go
+++ b/generated/macbridgeportfilterpre-assigntable.go
@@ -27,11 +27,11 @@
 
 // MacBridgePortFilterPreAssignTableClassID is the 16-bit ID for the OMCI
 // Managed entity MAC bridge port filter pre-assign table
-const MacBridgePortFilterPreAssignTableClassID ClassID = ClassID(79)
+const MacBridgePortFilterPreAssignTableClassID = ClassID(79) // 0x004f
 
 var macbridgeportfilterpreassigntableBME *ManagedEntityDefinition
 
-// MacBridgePortFilterPreAssignTable (class ID #79)
+// MacBridgePortFilterPreAssignTable (Class ID: #79 / 0x004f)
 //	This ME provides an alternate approach to DA filtering from that supported through the MAC
 //	bridge port filter table data ME. This alternate approach is useful when all groups of addresses
 //	are stored beforehand in the ONU, and the MAC bridge port filter pre-assign table ME designates
@@ -45,37 +45,48 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the MAC bridge port configuration
-//			data ME. (R) (mandatory) (2-bytes)
+//			The following 10 attributes have similar definitions. Each permits the OLT to specify whether
+//			MAC DAs or Ethertypes of the named type are forwarded (0) or filtered (1). In each case, the
+//			initial value of the attribute is 0.
+//
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the MAC bridge port configuration data ME. (R) (mandatory)
+//			(2-bytes)
 //
 //		Ipv4 Multicast Filtering
-//			IPv4 multicast filtering:	(R,-W) (mandatory) (1-byte)
+//			(R,-W) (mandatory) (1-byte)
 //
 //		Ipv6 Multicast Filtering
-//			IPv6 multicast filtering:	(R,-W) (mandatory) (1-byte)
+//			(R,-W) (mandatory) (1-byte)
 //
 //		Ipv4 Broadcast Filtering
-//			IPv4 broadcast filtering:	(R,-W) (mandatory) (1-byte)
+//			(R,-W) (mandatory) (1-byte)
 //
 //		Rarp Filtering
-//			RARP filtering:	(R,-W) (mandatory) (1-byte)
+//			(R,-W) (mandatory) (1-byte)
 //
 //		Ipx Filtering
-//			IPX filtering:		(R,-W) (mandatory) (1-byte)
+//				(R,-W) (mandatory) (1-byte)
 //
 //		Netbeui Filtering
-//			NetBEUI filtering:	(R,-W) (mandatory) (1-byte)
+//			(R,-W) (mandatory) (1-byte)
 //
 //		Appletalk Filtering
-//			AppleTalk filtering:	(R,-W) (mandatory) (1-byte)
+//			(R,-W) (mandatory) (1-byte)
 //
 //		Bridge Management Information Filtering
+//			(R,-W) (mandatory) (1-byte)
+//
+//			Note that some destination MAC addresses should never be forwarded, considering the following
+//			rules of [IEEE 802.1D].
+//
+//			1	Addresses from 01.80.C2.00.00.00 to 01.80.C2.00.00.0F are reserved.
+//
 //			2	Addresses from 01.80.C2.00.00.20 to 01.80.C2.00.00.2F are used for generic attribute
 //			registration protocol (GARP) applications.
 //
 //		Arp Filtering
-//			ARP filtering:	(R,-W) (mandatory) (1-byte)
+//			(R,-W) (mandatory) (1-byte)
 //
 //		Point_To_Point Protocol Over Ethernet Pppoe Broadcast Filtering
 //			Point-to-point protocol over Ethernet (PPPoE) broadcast filtering:	(R,-W) (mandatory) (1-byte)
diff --git a/generated/macbridgeportfiltertabledata.go b/generated/macbridgeportfiltertabledata.go
index 9e4e1cf..9d7cace 100644
--- a/generated/macbridgeportfiltertabledata.go
+++ b/generated/macbridgeportfiltertabledata.go
@@ -27,11 +27,11 @@
 
 // MacBridgePortFilterTableDataClassID is the 16-bit ID for the OMCI
 // Managed entity MAC bridge port filter table data
-const MacBridgePortFilterTableDataClassID ClassID = ClassID(49)
+const MacBridgePortFilterTableDataClassID = ClassID(49) // 0x0031
 
 var macbridgeportfiltertabledataBME *ManagedEntityDefinition
 
-// MacBridgePortFilterTableData (class ID #49)
+// MacBridgePortFilterTableData (Class ID: #49 / 0x0031)
 //	This ME organizes data associated with a bridge port. The ONU automatically creates or deletes
 //	an instance of this ME upon the creation or deletion of a MAC bridge port configuration data ME.
 //
@@ -44,11 +44,49 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the MAC bridge port configuration
-//			data ME. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the MAC bridge port configuration data ME. (R) (mandatory)
+//			(2-bytes)
 //
 //		Mac Filter Table
+//			This attribute lists MAC addresses associated with the bridge port, each with an allow/disallow
+//			forwarding indicator for traffic flowing out of the bridge port. Additionally, the forwarding
+//			action may be based on a MAC source or DA. In this way, upstream traffic is filtered on ANI-side
+//			bridge ports, and downstream traffic is filtered on UNI-side bridge ports. The setting of an
+//			entry with a forward action implies that all other addresses are filtered. Conversely, the
+//			setting of an entry with a filter action implies that all other addresses are forwarded. The
+//			behaviour is unspecified if forward and filter actions are mixed.
+//
+//			Each entry contains:
+//
+//			-	the entry number, an index into this attribute list (1-byte);
+//
+//			-	filter byte (1-byte);
+//
+//			-	MAC address (6-bytes).
+//
+//			The bits of the filter byte are assigned as follows.
+//
+//			Bit	Name	Setting
+//
+//			1 (LSB)	Filter/forward	0: forward
+//
+//			1: filter
+//
+//			2		0: MAC DAs
+//
+//			1: MAC source addresses
+//
+//			3..6	Reserved	0
+//
+//			7..8	Add/remove	10: Clear entire table (set operation)
+//
+//			00: Remove this entry (set operation)
+//
+//			01: Add this entry
+//
+//			Upon ME instantiation, the ONU sets this attribute to an empty table.
+//
 //			(R,-W) (Mandatory) (8N bytes, where N is the number of entries in the list)
 //
 type MacBridgePortFilterTableData struct {
diff --git a/generated/macbridgeporticmpv6processpre-assigntable.go b/generated/macbridgeporticmpv6processpre-assigntable.go
index 9467ca2..8131599 100644
--- a/generated/macbridgeporticmpv6processpre-assigntable.go
+++ b/generated/macbridgeporticmpv6processpre-assigntable.go
@@ -27,11 +27,11 @@
 
 // MacBridgePortIcmpv6ProcessPreAssignTableClassID is the 16-bit ID for the OMCI
 // Managed entity MAC bridge port ICMPv6 process pre-assign table
-const MacBridgePortIcmpv6ProcessPreAssignTableClassID ClassID = ClassID(348)
+const MacBridgePortIcmpv6ProcessPreAssignTableClassID = ClassID(348) // 0x015c
 
 var macbridgeporticmpv6processpreassigntableBME *ManagedEntityDefinition
 
-// MacBridgePortIcmpv6ProcessPreAssignTable (class ID #348)
+// MacBridgePortIcmpv6ProcessPreAssignTable (Class ID: #348 / 0x015c)
 //	This ME provides an approach to ICMPv6 message processing configuration to those ONUs that
 //	support IPv6 awareness. For every message, the MAC bridge port ICMPv6 process pre-assign table
 //	can designate a forward, discard or snoop operation. The ONU creates or deletes an instance of
@@ -47,39 +47,48 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the MAC bridge port configuration
-//			data ME. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the MAC bridge port configuration data ME. (R) (mandatory)
+//			(2-bytes)
+//
+//			The following nine attributes have similar definitions. Each permits the OLT to specify ICMPv6
+//			as the next header in the IPv6 header and various types in the ICMPv6 header, and whether
+//			traffic of the specified type is forwarded, discarded or snooped, in upstream and downstream
+//			directions separately. The bits of each attribute are assigned as follows.
+//
+//			The initial value of each attribute is given in the last column of the table.
 //
 //		Icmpv6 Error Messages Processing
-//			ICMPv6 error messages processing:	(R,-W) (mandatory) (1-byte)
+//			(R,-W) (mandatory) (1-byte)
 //
 //		Icmpv6 Informational Messages Processing
-//			ICMPv6 informational messages processing:	(R,-W) (mandatory) (1-byte)
+//			(R,-W) (mandatory) (1-byte)
 //
 //		Router Solicitation Processing
-//			Router solicitation processing:	(R,-W) (mandatory) (1-byte)
+//			(R,-W) (mandatory) (1-byte)
 //
 //		Router Advertisement Processing
-//			Router advertisement processing:	(R,-W) (mandatory) (1-byte)
+//			(R,-W) (mandatory) (1-byte)
 //
 //		Neighbour Solicitation Processing
-//			Neighbour solicitation processing:	(R,-W) (mandatory) (1-byte)
+//			(R,-W) (mandatory) (1-byte)
 //
 //		Neighbour Advertisement Processing
-//			Neighbour advertisement processing:	(R,-W) (mandatory) (1-byte)
+//			(R,-W) (mandatory) (1-byte)
 //
 //		Redirect Processing
-//			Redirect processing:	(R,-W) (mandatory) (1-byte)
+//			(R,-W) (mandatory) (1-byte)
 //
 //		Multicast Listener Query Processing
+//			(R,-W) (mandatory) (1-byte)
+//
 //			NOTE - If the ONU participates in multicast services, MLD queries should be controlled through
 //			the multicast operations profile ME. In such a case, it is strongly recommended not to provision
 //			the downstream direction of the multicast listener query processing attribute to any value other
 //			than forwarding.
 //
 //		Unknown Icmpv6 Processing
-//			Unknown ICMPv6 processing:	(R,-W) (mandatory) (1-byte)
+//			(R,-W) (mandatory) (1-byte)
 //
 type MacBridgePortIcmpv6ProcessPreAssignTable struct {
 	ManagedEntityDefinition
diff --git a/generated/macbridgeportperformancemonitoringhistorydata.go b/generated/macbridgeportperformancemonitoringhistorydata.go
index b416ff1..97b0e16 100644
--- a/generated/macbridgeportperformancemonitoringhistorydata.go
+++ b/generated/macbridgeportperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // MacBridgePortPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity MAC bridge port performance monitoring history data
-const MacBridgePortPerformanceMonitoringHistoryDataClassID ClassID = ClassID(52)
+const MacBridgePortPerformanceMonitoringHistoryDataClassID = ClassID(52) // 0x0034
 
 var macbridgeportperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// MacBridgePortPerformanceMonitoringHistoryData (class ID #52)
+// MacBridgePortPerformanceMonitoringHistoryData (Class ID: #52 / 0x0034)
 //	This ME collects PM data associated with a MAC bridge port. Instances of this ME are created and
 //	deleted by the OLT.
 //
@@ -43,13 +43,12 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the MAC bridge port configuration
-//			data ME. (R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the MAC bridge port configuration data ME. (R, setbycreate)
+//			(mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -57,24 +56,22 @@
 //			data 2 ME is optional. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Forwarded Frame Counter
-//			Forwarded frame counter: This attribute counts frames transmitted successfully on this port. (R)
-//			(mandatory) (4-bytes)
+//			This attribute counts frames transmitted successfully on this port. (R) (mandatory) (4-bytes)
 //
 //		Delay Exceeded Discard Counter
-//			Delay exceeded discard counter: This attribute counts frames discarded on this port because
-//			transmission was delayed. (R) (mandatory) (4-bytes)
+//			This attribute counts frames discarded on this port because transmission was delayed. (R)
+//			(mandatory) (4-bytes)
 //
 //		Maximum Transmission Unit Mtu Exceeded Discard Counter
 //			Maximum transmission unit (MTU) exceeded discard counter: This attribute counts frames discarded
 //			on this port because the MTU was exceeded. (R) (mandatory) (4-bytes)
 //
 //		Received Frame Counter
-//			Received frame counter: This attribute counts frames received on this port. (R) (mandatory)
-//			(4-bytes)
+//			This attribute counts frames received on this port. (R) (mandatory) (4-bytes)
 //
 //		Received And Discarded Counter
-//			Received and discarded counter: This attribute counts frames received on this port that were
-//			discarded due to errors. (R) (mandatory) (4-bytes)
+//			This attribute counts frames received on this port that were discarded due to errors. (R)
+//			(mandatory) (4-bytes)
 //
 type MacBridgePortPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/macbridgeserviceprofile.go b/generated/macbridgeserviceprofile.go
index ee5434c..c05d948 100644
--- a/generated/macbridgeserviceprofile.go
+++ b/generated/macbridgeserviceprofile.go
@@ -27,11 +27,11 @@
 
 // MacBridgeServiceProfileClassID is the 16-bit ID for the OMCI
 // Managed entity MAC bridge service profile
-const MacBridgeServiceProfileClassID ClassID = ClassID(45)
+const MacBridgeServiceProfileClassID = ClassID(45) // 0x002d
 
 var macbridgeserviceprofileBME *ManagedEntityDefinition
 
-// MacBridgeServiceProfile (class ID #45)
+// MacBridgeServiceProfile (Class ID: #45 / 0x002d)
 //	This ME models a MAC bridge in its entirety; any number of ports may be associated with the
 //	bridge through pointers to the MAC bridge service profile ME. Instances of this ME are created
 //	and deleted by the OLT.
@@ -43,56 +43,60 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The first byte
-//			is the slot ID. In an integrated ONU, this value is 0. The second byte is the bridge group ID.
-//			(R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. The first byte is the slot ID. In
+//			an integrated ONU, this value is 0. The second byte is the bridge group ID. (R, setbycreate)
+//			(mandatory) (2-bytes)
 //
 //		Spanning Tree Ind
-//			Spanning tree ind: The Boolean value true specifies that a spanning tree algorithm is enabled.
-//			The value false disables (rapid) spanning tree. (R,-W, setbycreate) (mandatory) (1-byte)
+//			The Boolean value true specifies that a spanning tree algorithm is enabled. The value false
+//			disables (rapid) spanning tree. (R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Learning Ind
-//			Learning ind: The Boolean value true specifies that bridge learning functions are enabled. The
-//			value false disables bridge learning. (R,-W, setbycreate) (mandatory) (1-byte)
+//			The Boolean value true specifies that bridge learning functions are enabled. The value false
+//			disables bridge learning. (R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Port Bridging Ind
-//			Port bridging ind: The Boolean value true specifies that bridging between UNI ports is enabled.
-//			The value false disables local bridging. (R,-W, setbycreate) (mandatory) (1-byte)
+//			The Boolean value true specifies that bridging between UNI ports is enabled. The value false
+//			disables local bridging. (R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Priority
-//			Priority:	This attribute specifies the bridge priority in the range 0..65535. The value of this
-//			attribute is copied to the bridge priority attribute of the associated MAC bridge configuration
-//			data ME. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute specifies the bridge priority in the range 0..65535. The value of this attribute
+//			is copied to the bridge priority attribute of the associated MAC bridge configuration data ME.
+//			(R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Max Age
-//			Max age:	This attribute specifies the maximum age (in 256ths of a second) of received protocol
+//			This attribute specifies the maximum age (in 256ths of a second) of received protocol
 //			information before its entry in the spanning tree listing is discarded. The range is 0x0600 to
 //			0x2800 (6..40-s) in accordance with [IEEE-802.1D]. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Hello Time
+//			This attribute specifies how often (in 256ths of a second) the bridge advertises its presence
+//			via hello packets, while acting as a root or attempting to become a root. The range is 0x0100 to
+//			0x0A00 (1..10-s). (R,-W, setbycreate) (mandatory) (2-bytes)
+//
 //			NOTE - [IEEE 802.1D] specifies the compatibility range for hello time to be 1..2-s.
 //
 //		Forward Delay
-//			Forward delay: This attribute specifies the forwarding delay (in 256ths of a second) when the
-//			bridge acts as the root. The range is 0x0400 to 0x1E00 (4..30-s) in accordance with [IEEE
-//			802.1D]. (R,-W, set-by-create) (mandatory) (2-bytes)
+//			This attribute specifies the forwarding delay (in 256ths of a second) when the bridge acts as
+//			the root. The range is 0x0400 to 0x1E00 (4..30-s) in accordance with [IEEE 802.1D]. (R,-W, set-
+//			by-create) (mandatory) (2-bytes)
 //
 //		Unknown Mac Address Discard
-//			Unknown MAC address discard: The Boolean value true specifies that MAC frames with unknown DAs
-//			be discarded. The value false specifies that such frames be forwarded to all allowed ports.
-//			(R,-W, setbycreate) (mandatory) (1-byte)
+//			The Boolean value true specifies that MAC frames with unknown DAs be discarded. The value false
+//			specifies that such frames be forwarded to all allowed ports. (R,-W, setbycreate) (mandatory)
+//			(1-byte)
 //
 //		Mac Learning Depth
-//			MAC learning depth: This attribute specifies the maximum number of UNI MAC addresses to be
-//			learned by the bridge. The default value 0 specifies that there is no administratively imposed
-//			limit. (R,-W, setbycreate) (optional) (1-byte)
+//			This attribute specifies the maximum number of UNI MAC addresses to be learned by the bridge.
+//			The default value 0 specifies that there is no administratively imposed limit. (R,-W,
+//			setbycreate) (optional) (1-byte)
 //
 //		Dynamic Filtering Ageing Time
-//			Dynamic filtering ageing time: This attribute specifies the age of dynamic filtering entries in
-//			the bridge database, after which unrefreshed entries are discarded. In accordance with clause
-//			7.9.2 of [IEEE 802.1D] and clause 8.8.3 of [IEEE 802.1Q], the range is 10..1 000 000-s, with a
-//			resolution of 1-s and a default of 300-s. The value 0 specifies that the ONU uses its internal
-//			default. (R, W, set-by-create) (optional) (4 bytes)
+//			This attribute specifies the age of dynamic filtering entries in the bridge database, after
+//			which unrefreshed entries are discarded. In accordance with clause 7.9.2 of [IEEE 802.1D] and
+//			clause 8.8.3 of [IEEE 802.1Q], the range is 10..1 000 000-s, with a resolution of 1-s and a
+//			default of 300-s. The value 0 specifies that the ONU uses its internal default. (R, W, set-by-
+//			create) (optional) (4 bytes)
 //
 type MacBridgeServiceProfile struct {
 	ManagedEntityDefinition
diff --git a/generated/managedentityme.go b/generated/managedentityme.go
index b716b09..91354b5 100644
--- a/generated/managedentityme.go
+++ b/generated/managedentityme.go
@@ -27,11 +27,11 @@
 
 // ManagedEntityMeClassID is the 16-bit ID for the OMCI
 // Managed entity Managed entity ME
-const ManagedEntityMeClassID ClassID = ClassID(288)
+const ManagedEntityMeClassID = ClassID(288) // 0x0120
 
 var managedentitymeBME *ManagedEntityDefinition
 
-// ManagedEntityMe (class ID #288)
+// ManagedEntityMe (Class ID: #288 / 0x0120)
 //	The ME describes the details of each ME that is supported by the ONU. This ME is not included in
 //	an MIB upload.
 //
@@ -40,39 +40,62 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Its value is
-//			equal to the ME type value, and is the same as the code found in the ME type table attribute of
-//			the OMCI ME and Table-11.2.41. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Its value is equal to the ME type
+//			value, and is the same as the code found in the ME type table attribute of the OMCI ME and
+//			Table-11.2.41. (R) (mandatory) (2-bytes)
 //
 //		Name
-//			Name:	This attribute contains a 25-byte ASCII coded mnemonic tag for the ME type. Strings
-//			shorter than 25-bytes are padded with null characters. (R) (mandatory) (25-bytes)
+//			This attribute contains a 25-byte ASCII coded mnemonic tag for the ME type. Strings shorter than
+//			25-bytes are padded with null characters. (R) (mandatory) (25-bytes)
 //
 //		Attributes Table
+//			This table contains pointers to the attribute MEs that describe each of this ME's attributes.
+//			(R) (mandatory) (2 * X bytes, where X is the number of entries in the table.)
+//
 //			NOTE - The ME ID attribute is not included in the list, since the type of this attribute is
 //			fixed.
 //
 //		Access
+//			This attribute represents who creates this ME. The following code points are defined.
+//
+//			1	Created by the ONU
+//
+//			2	Created by the OLT
+//
+//			3	Created by both the ONU and OLT
+//
 //			(R) (mandatory) (1-byte)
 //
 //		Alarms Table
-//			Alarms table: This attribute lists the alarm codes that are supported. (R) (mandatory) (Y bytes,
-//			where Y is the number of entries in the table.)
+//			This attribute lists the alarm codes that are supported. (R) (mandatory) (Y bytes, where Y is
+//			the number of entries in the table.)
 //
 //		Avcs Table
-//			AVCs table:	This attribute lists the AVCs that are supported. (R) (mandatory) (Z bytes, where Z
-//			is the number of entries in the table.)
+//			This attribute lists the AVCs that are supported. (R) (mandatory) (Z bytes, where Z is the
+//			number of entries in the table.)
 //
 //		Actions
-//			Actions:	This attribute lists the action codes supported on this object, formatted as a bit map.
-//			The action codes are the MTs from Table-11.2.2-1. The LSB represents action 0, and so on. (R)
+//			This attribute lists the action codes supported on this object, formatted as a bit map. The
+//			action codes are the MTs from Table-11.2.2-1. The LSB represents action 0, and so on. (R)
 //			(mandatory) (4-bytes)
 //
 //		Instances Table
-//			Instances table: This attribute is a list of pointers to all instances of this ME. (R)
-//			(mandatory) (2 * V bytes, where V is the number of entries in the table.)
+//			This attribute is a list of pointers to all instances of this ME. (R) (mandatory) (2 * V bytes,
+//			where V is the number of entries in the table.)
 //
 //		Support
+//			This attribute represents the support capability of this ME in the ONU's implementation. This
+//			attribute does not declare whether the OMCI implementation complies with the Recommendations,
+//			but whether it complies with the OMCI declaration itself. The following code points are defined.
+//
+//			1	Supported (supported as defined in this object)
+//
+//			2	Unsupported (OMCI returns error code if accessed)
+//
+//			3	Partially supported (some aspects of ME supported)
+//
+//			4	Ignored (OMCI supported, but underlying function is not)
+//
 //			(R) (mandatory) (1-byte)
 //
 type ManagedEntityMe struct {
diff --git a/generated/medef.go b/generated/medef.go
index 4e91db6..d6ab352 100644
--- a/generated/medef.go
+++ b/generated/medef.go
@@ -91,8 +91,8 @@
 
 func (bme ManagedEntityDefinition) DecodeAttributes(mask uint16, data []byte, p gopacket.PacketBuilder, msgType byte) (AttributeValueMap, error) {
 	if (mask | bme.GetAllowedAttributeMask()) != bme.GetAllowedAttributeMask() {
-		// TODO: Provide custom error code so a response 'result' can properly be coded
-		return nil, errors.New("unsupported attribute mask")
+		return nil, fmt.Errorf("unsupported attribute mask %#x, valid: %#x for ME %v (Class ID: %d)",
+			mask, bme.GetAllowedAttributeMask(), bme.GetName(), bme.ClassID)
 	}
 	keyList := GetAttributeDefinitionMapKeys(bme.AttributeDefinitions)
 
@@ -144,8 +144,8 @@
 					// TODO: No support at this time
 
 				case byte(SetTable) | AR: // Set Table Request
-					// TODO: Only baseline supported at this time
-					return nil, errors.New("attribute encode for set-table-request not yet supported")
+					attrMap[name] = value
+					data = data[len(data):]
 				}
 			} else {
 				attrMap[name] = value
diff --git a/generated/mgcconfigdata.go b/generated/mgcconfigdata.go
index ddd39fb..4b97077 100644
--- a/generated/mgcconfigdata.go
+++ b/generated/mgcconfigdata.go
@@ -27,11 +27,11 @@
 
 // MgcConfigDataClassID is the 16-bit ID for the OMCI
 // Managed entity MGC config data
-const MgcConfigDataClassID ClassID = ClassID(155)
+const MgcConfigDataClassID = ClassID(155) // 0x009b
 
 var mgcconfigdataBME *ManagedEntityDefinition
 
-// MgcConfigData (class ID #155)
+// MgcConfigData (Class ID: #155 / 0x009b)
 //	The MGC config data ME defines the MGC configuration associated with an MG subscriber. It is
 //	conditionally required for ONUs that support ITU-T H.248 VoIP services. If a non-OMCI interface
 //	is used to manage VoIP signalling, this ME is unnecessary.
@@ -43,63 +43,69 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Primary Mgc
-//			Primary MGC: This attribute points to a network address ME that contains the name (IP-address or
-//			resolved name) of the primary MGC that controls the signalling messages. The port is optional
-//			and defaults to 2944 for text message formats and 2955 for binary message formats. (R,-W,
+//			This attribute points to a network address ME that contains the name (IP-address or resolved
+//			name) of the primary MGC that controls the signalling messages. The port is optional and
+//			defaults to 2944 for text message formats and 2955 for binary message formats. (R,-W,
 //			setbycreate) (mandatory) (2-bytes)
 //
 //		Secondary Mgc
-//			Secondary MGC: This attribute points to a network address ME that contains the name (IP-address
-//			or resolved name) of the secondary or backup MGC that controls the signalling messages. The port
-//			is optional and defaults to 2944 for text message formats and 2955 for binary message formats.
-//			(R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute points to a network address ME that contains the name (IP-address or resolved
+//			name) of the secondary or backup MGC that controls the signalling messages. The port is optional
+//			and defaults to 2944 for text message formats and 2955 for binary message formats. (R,-W,
+//			setbycreate) (mandatory) (2-bytes)
 //
 //		Tcp_Udp Pointer
 //			TCP/UDP pointer: This attribute points to the TCP/UDP config data ME to be used for
 //			communication with the MGC. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Version
-//			Version:	This integer attribute reports the version of the Megaco protocol in use. The ONU
-//			should deny an attempt by the OLT to set or create a value that it does not support. The value 0
-//			indicates that no particular version is specified. (R,-W, setbycreate) (mandatory) (1-byte)
+//			This integer attribute reports the version of the Megaco protocol in use. The ONU should deny an
+//			attempt by the OLT to set or create a value that it does not support. The value 0 indicates that
+//			no particular version is specified. (R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Message Format
+//			This attribute defines the message format. Valid values are as follows.
+//
+//			0	Text long
+//
+//			1	Text short
+//
+//			2	Binary
+//
 //			The default value is recommended to be 0. (R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Maximum Retry Time
-//			Maximum retry time: This attribute specifies the maximum retry time for MGC transactions, in
-//			seconds. The default value 0 specifies vendor-specific implementation. (R,-W) (optional)
-//			(2-bytes)
+//			This attribute specifies the maximum retry time for MGC transactions, in seconds. The default
+//			value 0 specifies vendor-specific implementation. (R,-W) (optional) (2-bytes)
 //
 //		Maximum Retry Attempts
-//			Maximum retry attempts: This attribute specifies the maximum number of times a message is
-//			retransmitted to the MGC. The recommended default value 0 specifies vendor-specific
-//			implementation. (R,-W, setbycreate) (optional) (2-bytes)
+//			This attribute specifies the maximum number of times a message is retransmitted to the MGC. The
+//			recommended default value 0 specifies vendor-specific implementation. (R,-W, setbycreate)
+//			(optional) (2-bytes)
 //
 //		Service Change Delay
-//			Service change delay: This attribute specifies the service status delay time for changes in line
-//			service status. This attribute is specified in seconds. The default value 0 specifies no delay.
-//			(R,-W) (optional) (2-bytes)
+//			This attribute specifies the service status delay time for changes in line service status. This
+//			attribute is specified in seconds. The default value 0 specifies no delay. (R,-W) (optional)
+//			(2-bytes)
 //
 //		Termination Id Base
-//			Termination ID base: This attribute specifies the base string for the ITU-T H.248 physical
-//			termination ID(s) for this ONU. This string is intended to uniquely identify an ONU. Vendor-
-//			specific termination identifiers (port IDs) are optionally added to this string to uniquely
-//			identify a termination on a specific ONU. (R,-W) (optional) (25-bytes)
+//			This attribute specifies the base string for the ITU-T H.248 physical termination ID(s) for this
+//			ONU. This string is intended to uniquely identify an ONU. Vendor-specific termination
+//			identifiers (port IDs) are optionally added to this string to uniquely identify a termination on
+//			a specific ONU. (R,-W) (optional) (25-bytes)
 //
 //		Softswitch
-//			Softswitch:	This attribute identifies the gateway softswitch vendor. The format is four ASCII
-//			coded alphabetic characters [A..Z] as defined in [ATIS0300220]. A value of four null bytes
-//			indicates an unknown or unspecified vendor. (R,-W, setbycreate) (mandatory) (4-bytes)
+//			This attribute identifies the gateway softswitch vendor. The format is four ASCII coded
+//			alphabetic characters [A..Z] as defined in [ATIS0300220]. A value of four null bytes indicates
+//			an unknown or unspecified vendor. (R,-W, setbycreate) (mandatory) (4-bytes)
 //
 //		Message Id Pointer
-//			Message ID pointer: This attribute points to a large string whose value specifies the message
-//			identifier string for ITU-T H.248 messages originated by the ONU. (R, W, setbycreate) (optional)
-//			(2 bytes)
+//			This attribute points to a large string whose value specifies the message identifier string for
+//			ITU-T H.248 messages originated by the ONU. (R, W, setbycreate) (optional) (2 bytes)
 //
 type MgcConfigData struct {
 	ManagedEntityDefinition
diff --git a/generated/mgcconfigportal.go b/generated/mgcconfigportal.go
new file mode 100644
index 0000000..46167fa
--- /dev/null
+++ b/generated/mgcconfigportal.go
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+/*
+ * NOTE: This file was generated, manual edits will be overwritten!
+ *
+ * Generated by 'goCodeGenerator.py':
+ *              https://github.com/cboling/OMCI-parser/README.md
+ */
+
+package generated
+
+import "github.com/deckarep/golang-set"
+
+// MgcConfigPortalClassID is the 16-bit ID for the OMCI
+// Managed entity MGC config portal
+const MgcConfigPortalClassID = ClassID(154) // 0x009a
+
+var mgcconfigportalBME *ManagedEntityDefinition
+
+// MgcConfigPortal (Class ID: #154 / 0x009a)
+//	The MGC config portal ME provides a way for the OLT to discover the configuration text delivered
+//	to an ONU by a non-OMCI ITU-T H.248 VoIP configuration method. Text retrieved from this ME is
+//	not required to be understood by the OLT or EMS, but it may be useful for human or vendor-
+//	specific analysis tools. See also the SIP config portal ME.
+//
+//	An instance of this ME may be created by an ONU that supports non-OMCI ITUT-H.248 configuration.
+//	It is not reported during an MIB upload.
+//
+//	Relationships
+//		One instance of this ME is associated with the ONU.
+//
+//	Attributes
+//		Managed Entity Id
+//			This attribute uniquely identifies each instance of this ME. There is one instance, number 0.
+//			(R, setbycreate) (mandatory) (2-bytes)
+//
+//		Configuration Text Table
+//			This attribute is used to pass a textual representation of the VoIP configuration back to the
+//			OLT. The contents are vendor-specific. The get, get next sequence must be used with this
+//			attribute since its size is unspecified. Upon ME instantiation, the ONU sets this attribute to
+//			0. (R) (mandatory) (x bytes)
+//
+type MgcConfigPortal struct {
+	ManagedEntityDefinition
+	Attributes AttributeValueMap
+}
+
+func init() {
+	mgcconfigportalBME = &ManagedEntityDefinition{
+		Name:    "MgcConfigPortal",
+		ClassID: 154,
+		MessageTypes: mapset.NewSetWith(
+			Get,
+			GetNext,
+		),
+		AllowedAttributeMask: 0x8000,
+		AttributeDefinitions: AttributeDefinitionMap{
+			0: Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read, SetByCreate), false, false, false, 0),
+			1: TableField("ConfigurationTextTable", TableAttributeType, 0x8000, TableInfo{nil, 25}, mapset.NewSetWith(Read), true, false, false, 1),
+		},
+		Access:  CreatedByOnu,
+		Support: UnknownSupport,
+	}
+}
+
+// NewMgcConfigPortal (class ID 154) creates the basic
+// Managed Entity definition that is used to validate an ME of this type that
+// is received from or transmitted to the OMCC.
+func NewMgcConfigPortal(params ...ParamData) (*ManagedEntity, OmciErrors) {
+	return NewManagedEntity(*mgcconfigportalBME, params...)
+}
diff --git a/generated/mgcperformancemonitoringhistorydata.go b/generated/mgcperformancemonitoringhistorydata.go
index 7a4e457..082de74 100644
--- a/generated/mgcperformancemonitoringhistorydata.go
+++ b/generated/mgcperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // MgcPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity MGC performance monitoring history data
-const MgcPerformanceMonitoringHistoryDataClassID ClassID = ClassID(156)
+const MgcPerformanceMonitoringHistoryDataClassID = ClassID(156) // 0x009c
 
 var mgcperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// MgcPerformanceMonitoringHistoryData (class ID #156)
+// MgcPerformanceMonitoringHistoryData (Class ID: #156 / 0x009c)
 //	The MGC monitoring data ME provides run-time statistics for an active MGC association. Instances
 //	of this ME are created and deleted by the OLT.
 //
@@ -43,15 +43,13 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the associated MGC config data or
-//			to the MGC config portal ME. If a non-OMCI configuration method is used for VoIP, there can be
-//			only one live ME instance, associated with the MGC config portal, and with ME ID 0. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the associated MGC config data or to the MGC config portal
+//			ME. If a non-OMCI configuration method is used for VoIP, there can be only one live ME instance,
+//			associated with the MGC config portal, and with ME ID 0. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -59,41 +57,66 @@
 //			data 2 ME is optional. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Received Messages
-//			Received messages: This attribute counts the number of received Megaco messages on this
-//			association, as defined by [ITUT H.341]. (R) (mandatory) (4-bytes)
+//			This attribute counts the number of received Megaco messages on this association, as defined by
+//			[ITUT H.341]. (R) (mandatory) (4-bytes)
 //
 //		Received Octets
-//			Received octets: This attribute counts the total number of octets received on this association,
-//			as defined by [ITU-T H.341]. (R) (mandatory) (4-bytes)
+//			This attribute counts the total number of octets received on this association, as defined by
+//			[ITU-T H.341]. (R) (mandatory) (4-bytes)
 //
 //		Sent Messages
-//			Sent messages: This attribute counts the total number of Megaco messages sent over this
-//			association, as defined by [ITU-T H.341]. (R) (mandatory) (4-bytes)
+//			This attribute counts the total number of Megaco messages sent over this association, as defined
+//			by [ITU-T H.341]. (R) (mandatory) (4-bytes)
 //
 //		Sent Octets
-//			Sent octets:	This attribute counts the total number of octets sent over this association, as
-//			defined by [ITU-T H.341]. (R) (mandatory) (4-bytes)
+//			This attribute counts the total number of octets sent over this association, as defined by
+//			[ITU-T H.341]. (R) (mandatory) (4-bytes)
 //
 //		Protocol Errors
+//			This attribute counts the total number of errors detected on this association, as defined by
+//			[ITU-T H.341]. This includes:
+//
+//			o	syntax errors detected in a given received message;
+//
+//			o	outgoing transactions that failed for protocol reasons.
+//
 //			(R) (mandatory) (4-bytes)
 //
 //		Transport Losses
-//			Transport losses: This attribute counts the total number of transport losses (e.g., socket
-//			problems) detected on this association. A link loss is defined as loss of communication with the
-//			remote entity due to hardware/transient problems, or problems in related software. (R)
-//			(mandatory) (4-bytes)
+//			This attribute counts the total number of transport losses (e.g., socket problems) detected on
+//			this association. A link loss is defined as loss of communication with the remote entity due to
+//			hardware/transient problems, or problems in related software. (R) (mandatory) (4-bytes)
 //
 //		Last Detected Event
+//			This attribute reports the last event detected on this association. This includes events such as
+//			the link failing or being set up. Under normal circumstances, a get action on this attribute
+//			would return 0 to indicate no abnormal activity. This field is an enumeration as follows.
+//
+//			0	No event - No event has yet been detected during this PM interval.
+//
+//			1	Link up - The transport link underpinning the association came up.
+//
+//			2	Link down - The transport link underpinning the association went down.
+//
+//			3	Persistent error - A persistent error was detected on the link (such as the socket/TCP
+//			connection to the remote node could not be set up).
+//
+//			4	Local shutdown - The association was brought down intentionally by the local application.
+//
+//			5	Failover down - The association was brought down as part of failover processing.
+//
+//			255	Other event - The latest event does not match any in the list.
+//
 //			(R) (mandatory) (1-byte)
 //
 //		Last Detected Event Time
-//			Last detected event time: This attribute reports the time in seconds since the last event on
-//			this association was detected, as defined by [ITU-T H.341]. (R) (mandatory) (4-bytes)
+//			This attribute reports the time in seconds since the last event on this association was
+//			detected, as defined by [ITU-T H.341]. (R) (mandatory) (4-bytes)
 //
 //		Last Detected Reset Time
-//			Last detected reset time: This attribute reports the time in seconds since these statistics were
-//			last reset, as defined by [ITU-T H.341]. Under normal circumstances, a get action on this
-//			attribute would return 900-s to indicate a completed 15-min interval. (R) (mandatory) (4-bytes)
+//			This attribute reports the time in seconds since these statistics were last reset, as defined by
+//			[ITU-T H.341]. Under normal circumstances, a get action on this attribute would return 900-s to
+//			indicate a completed 15-min interval. (R) (mandatory) (4-bytes)
 //
 type MgcPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/mocaethernetperformancemonitoringhistorydata.go b/generated/mocaethernetperformancemonitoringhistorydata.go
index b66845c..c69d00b 100644
--- a/generated/mocaethernetperformancemonitoringhistorydata.go
+++ b/generated/mocaethernetperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // MocaEthernetPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity MoCA Ethernet performance monitoring history data
-const MocaEthernetPerformanceMonitoringHistoryDataClassID ClassID = ClassID(163)
+const MocaEthernetPerformanceMonitoringHistoryDataClassID = ClassID(163) // 0x00a3
 
 var mocaethernetperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// MocaEthernetPerformanceMonitoringHistoryData (class ID #163)
+// MocaEthernetPerformanceMonitoringHistoryData (Class ID: #163 / 0x00a3)
 //	This ME collects PM data for an MoCA Ethernet interface. Instances of this ME are created and
 //	deleted by the OLT.
 //
@@ -42,59 +42,60 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP MoCA UNI. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP MoCA UNI. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 and 2 MEs
 //			that contains PM threshold values. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
+//			Incoming PM refers to upstream traffic received on the UNI; outgoing PM refers to downstream
+//			traffic transmitted on the UNI.
+//
 //		Incoming Unicast Packets
-//			Incoming unicast packets:	(R) (optional) (4-bytes)
+//			(R) (optional) (4-bytes)
 //
 //		Incoming Discarded Packets
-//			Incoming discarded packets:	(R) (optional) (4-bytes)
+//			(R) (optional) (4-bytes)
 //
 //		Incoming Errored Packets
-//			Incoming errored packets:	(R) (optional) (4-bytes)
+//			(R) (optional) (4-bytes)
 //
 //		Incoming Unknown Packets
-//			Incoming unknown packets:	(R) (optional) (4-bytes)
+//			(R) (optional) (4-bytes)
 //
 //		Incoming Multicast Packets
-//			Incoming multicast packets:	(R) (optional) (4-bytes)
+//			(R) (optional) (4-bytes)
 //
 //		Incoming Broadcast Packets
-//			Incoming broadcast packets:	(R) (optional) (4-bytes)
+//			(R) (optional) (4-bytes)
 //
 //		Incoming Octets
-//			Incoming octets:	(R) (optional) (4-bytes)
+//			(R) (optional) (4-bytes)
 //
 //		Outgoing Unicast Packets
-//			Outgoing unicast packets:	(R) (optional) (4-bytes)
+//			(R) (optional) (4-bytes)
 //
 //		Outgoing Discarded Packets
-//			Outgoing discarded packets:	(R) (optional) (4-bytes)
+//			(R) (optional) (4-bytes)
 //
 //		Outgoing Errored Packets
-//			Outgoing errored packets:	(R) (optional) (4-bytes)
+//			(R) (optional) (4-bytes)
 //
 //		Outgoing Unknown Packets
-//			Outgoing unknown packets:	(R) (optional) (4-bytes)
+//			(R) (optional) (4-bytes)
 //
 //		Outgoing Multicast Packets
-//			Outgoing multicast packets:	(R) (optional) (4-bytes)
+//			(R) (optional) (4-bytes)
 //
 //		Outgoing Broadcast Packets
-//			Outgoing broadcast packets:	(R) (optional) (4-bytes)
+//			(R) (optional) (4-bytes)
 //
 //		Outgoing Octets
-//			Outgoing octets:	(R) (optional) (4-bytes)
+//			(R) (optional) (4-bytes)
 //
 type MocaEthernetPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/mocainterfaceperformancemonitoringhistorydata.go b/generated/mocainterfaceperformancemonitoringhistorydata.go
new file mode 100644
index 0000000..41b3aa1
--- /dev/null
+++ b/generated/mocainterfaceperformancemonitoringhistorydata.go
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+/*
+ * NOTE: This file was generated, manual edits will be overwritten!
+ *
+ * Generated by 'goCodeGenerator.py':
+ *              https://github.com/cboling/OMCI-parser/README.md
+ */
+
+package generated
+
+import "github.com/deckarep/golang-set"
+
+// MocaInterfacePerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
+// Managed entity MoCA interface performance monitoring history data
+const MocaInterfacePerformanceMonitoringHistoryDataClassID = ClassID(164) // 0x00a4
+
+var mocainterfaceperformancemonitoringhistorydataBME *ManagedEntityDefinition
+
+// MocaInterfacePerformanceMonitoringHistoryData (Class ID: #164 / 0x00a4)
+//	This ME collects PM data for an MoCA interface. Instances of this ME are created and deleted by
+//	the OLT.
+//
+//	NOTE - The structure of this ME is an exception to the normal definition of PM MEs and normal PM
+//	behaviour (clause I.4). It should not be used as a guide for the definition of future MEs. Among
+//	other exceptions, this ME contains only current values, which are retrievable by get and get
+//	next operations; no history is retained.
+//
+//	Relationships
+//		An instance of this ME is associated with an instance of the PPTP MoCA UNI ME.
+//
+//	Attributes
+//		Managed Entity Id
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP MoCA UNI. (R, setbycreate) (mandatory) (2-bytes)
+//
+//		Interval End Time
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
+//
+//		Threshold Data 1_2 Id
+//			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
+//			contains PM threshold values. Since no threshold value attribute number exceeds 7, a threshold
+//			data 2 ME is optional. (R,-W, setbycreate) (mandatory) (2-bytes)
+//
+//		Phy T X Broadcast Rate
+//			PHY Tx broadcast rate: This attribute indicates the MoCA PHY broadcast transmit rate from the
+//			ONU MoCA interface to all the nodes in bits per second. (R) (optional) (4-bytes)
+//
+//		Node Table
+//			Rx packet: Number of packets received from the node. (4-bytes)
+//
+//			Rx errored and missed: Number of errored and missed packets received from the node. The sum of
+//			this field across all entries in the node table contributes to the Rx errored and missed TCA.
+//			This field is reset to 0 on 15-min boundaries. (4-bytes)
+//
+//			Rx errored: Number of errored packets received from the node. The sum of this field across all
+//			entries in the node table contributes to the Rx errored TCA. This field is reset to 0 on 15-min
+//			boundaries. (optional) (4-bytes)
+//
+//			(R) (mandatory) (37 * N bytes, where N is the number of nodes in the node table)
+//
+//			This attribute lists current nodes in the node table. The table contains MAC addresses and
+//			statistics for those nodes. These table attributes are further described in the following. Space
+//			for nonsupported optional fields must be allocated in table records, and filled with zero bytes.
+//
+//			MAC address: A unique identifier of a node within the table. (6-bytes)
+//
+//			PHY Tx rate: MoCA PHY unicast transmit rate from the ONU MoCA interface to the node identified
+//			by the MAC address, in bits per second. (4-bytes)
+//
+//			Tx power control reduction: The reduction in transmitter level due to power control, in
+//			decibels. Valid values range from 0 (full power) to 60. (1-byte)
+//
+//			PHY Rx rate: MoCA PHY unicast receive rate to the ONU MoCA interface from the node identified by
+//			the MAC address, in bits per second. (optional) (4-bytes)
+//
+//			Rx power level: The power level received at the ONU MoCA interface from the node identified by
+//			the MAC address, in decibel-milliwatts, represented as a 2s complement integer. Valid values
+//			range from +10 (0x0A) to -80 (0xB0). (1-byte)
+//
+//			PHY Rx broadcast rate: MoCA PHY broadcast receive rate to the ONU MoCA interface from the node
+//			identified by MAC address, in bits per second. (optional) (4-bytes)
+//
+//			Rx broadcast power level: The power level received at the ONU MoCA interface from the node
+//			identified by the MAC address, in decibel-milliwatts, represented as a 2s complement integer.
+//			Valid values range from +10-(0x0A) to -80 (0xB0). (1-byte)
+//
+//			Tx packet: Number of packets transmitted to the node. (4-bytes)
+//
+type MocaInterfacePerformanceMonitoringHistoryData struct {
+	ManagedEntityDefinition
+	Attributes AttributeValueMap
+}
+
+func init() {
+	mocainterfaceperformancemonitoringhistorydataBME = &ManagedEntityDefinition{
+		Name:    "MocaInterfacePerformanceMonitoringHistoryData",
+		ClassID: 164,
+		MessageTypes: mapset.NewSetWith(
+			Create,
+			Delete,
+			Get,
+			GetNext,
+			Set,
+		),
+		AllowedAttributeMask: 0xf000,
+		AttributeDefinitions: AttributeDefinitionMap{
+			0: Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read, SetByCreate), false, false, false, 0),
+			1: ByteField("IntervalEndTime", UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read), false, false, false, 1),
+			2: Uint16Field("ThresholdData12Id", UnsignedIntegerAttributeType, 0x4000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 2),
+			3: Uint32Field("PhyTXBroadcastRate", CounterAttributeType, 0x2000, 0, mapset.NewSetWith(Read), false, true, false, 3),
+			4: TableField("NodeTable", TableAttributeType, 0x1000, TableInfo{nil, 37}, mapset.NewSetWith(Read), false, false, false, 4),
+		},
+		Access:  CreatedByOlt,
+		Support: UnknownSupport,
+		Alarms: AlarmMap{
+			0: "Total rx errored and missed",
+			1: "Total rx errored",
+		},
+	}
+}
+
+// NewMocaInterfacePerformanceMonitoringHistoryData (class ID 164) creates the basic
+// Managed Entity definition that is used to validate an ME of this type that
+// is received from or transmitted to the OMCC.
+func NewMocaInterfacePerformanceMonitoringHistoryData(params ...ParamData) (*ManagedEntity, OmciErrors) {
+	return NewManagedEntity(*mocainterfaceperformancemonitoringhistorydataBME, params...)
+}
diff --git a/generated/mplspseudowireterminationpoint.go b/generated/mplspseudowireterminationpoint.go
index ccd5697..ed2ec34 100644
--- a/generated/mplspseudowireterminationpoint.go
+++ b/generated/mplspseudowireterminationpoint.go
@@ -27,11 +27,11 @@
 
 // MplsPseudowireTerminationPointClassID is the 16-bit ID for the OMCI
 // Managed entity MPLS pseudowire termination point
-const MplsPseudowireTerminationPointClassID ClassID = ClassID(333)
+const MplsPseudowireTerminationPointClassID = ClassID(333) // 0x014d
 
 var mplspseudowireterminationpointBME *ManagedEntityDefinition
 
-// MplsPseudowireTerminationPoint (class ID #333)
+// MplsPseudowireTerminationPoint (Class ID: #333 / 0x014d)
 //	This ME contains the configuration data of a pseudowire whose underlying transport method is
 //	MPLS. Instances of this ME are created and deleted by the OLT.
 //
@@ -40,69 +40,131 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R,
-//			setbycreate)-(mandatory) (2 bytes)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate)-(mandatory) (2
+//			bytes)
 //
 //		Tp Type
+//			This attribute specifies the type of ANI-side TP associated with this-ME.
+//
+//			1	Ethernet flow termination point
+//
+//			2	GEM IW TP
+//
+//			3	TCP/UDP config data
+//
+//			4	MPLS pseudowire termination point
+//
+//			NOTE - If this instance of the MPLS PW TP is pointed to by another instance of the MPLS PW TP
+//			(i.e., whose TP type-= 4), this instance represents a tunnelled MPLS flow, and the following
+//			attributes are not meaningful: MPLS PW direction; MPLS PW uplink label; MPLS PW downlink label;
+//			and MPLS PW TC. These attributes should be set to the proper number of 0x00 bytes by the OLT and
+//			ignored by the ONU.
+//
 //			(R, W, setbycreate) (mandatory) (1 byte)
 //
 //		Tp Pointer
-//			TP pointer:	This attribute points to the instance of the TP associated with this MPLS PW TP. The
-//			type of the associated TP is determined by the TP type attribute. (R, W, setbycreate)
-//			(mandatory) (2 bytes)
+//			This attribute points to the instance of the TP associated with this MPLS PW TP. The type of the
+//			associated TP is determined by the TP type attribute. (R, W, setbycreate) (mandatory) (2 bytes)
 //
 //		Mpls Label Indicator
+//			This attribute specifies the MPLS label stacking situation.
+//
+//			0	Single MPLS labelled
+//
+//			1	Double MPLS labelled
+//
 //			(R, W, setbycreate) (mandatory) (1 byte)
 //
 //		Mpls Pw Direction
+//			This attribute specifies the inner MPLS direction.
+//
+//			0	Upstream only
+//
+//			1	Downstream only
+//
+//			2	Bidirectional
+//
 //			(R, W, setbycreate) (mandatory) (1 byte)
 //
 //		Mpls Pw Uplink Label
-//			MPLS PW uplink label: This attribute specifies the label of the inner MPLS pseudowire upstream.
-//			The attribute is not meaningful for unidirectional downstream PWs. (R, W, setbycreate)
-//			(mandatory) (4 bytes)
+//			This attribute specifies the label of the inner MPLS pseudowire upstream. The attribute is not
+//			meaningful for unidirectional downstream PWs. (R, W, setbycreate) (mandatory) (4 bytes)
 //
 //		Mpls Pw Downlink Label
-//			MPLS PW downlink label: This attribute specifies the label of the inner MPLS pseudowire
-//			downstream. The attribute is not meaningful for unidirectional upstream PWs. (R, W, setbycreate)
-//			(mandatory) (4 bytes)
+//			This attribute specifies the label of the inner MPLS pseudowire downstream. The attribute is not
+//			meaningful for unidirectional upstream PWs. (R, W, setbycreate) (mandatory) (4 bytes)
 //
 //		Mpls Pw Tc
 //			NOTE 1 - The TC field was previously known as EXP. Refer to [bIETF-RFC-5462].
 //
+//			This attribute specifies the inner MPLS TC value in the upstream direction. The attribute is not
+//			meaningful for unidirectional downstream PWs. (R, W, setbycreate) (mandatory) (1 byte)
+//
 //		Mpls Tunnel Direction
+//			This attribute specifies the direction of the (outer) MPLS tunnel.
+//
+//			0	Upstream only
+//
+//			1	Downstream only
+//
+//			2	Bidirectional
+//
 //			(R, W, setbycreate) (mandatory for double-labelled case) (1 byte)
 //
 //		Mpls Tunnel Uplink Label
-//			MPLS tunnel uplink label: This attribute specifies the (outer) label for the upstream MPLS
-//			tunnel. If the MPLS tunnel is downstream only, this attribute should be set to 0. (R, W,
-//			setbycreate) (mandatory for double-labelled case) (4 bytes)
+//			This attribute specifies the (outer) label for the upstream MPLS tunnel. If the MPLS tunnel is
+//			downstream only, this attribute should be set to 0. (R, W, setbycreate) (mandatory for double-
+//			labelled case) (4 bytes)
 //
 //		Mpls Tunnel Downlink Label
-//			MPLS tunnel downlink label: This attribute specifies the (outer) label for the downstream MPLS
-//			tunnel. If the MPLS tunnel is upstream only, this attribute should be set to 0. (R, W,
-//			setbycreate) (mandatory for double-labelled case) (4 bytes)
+//			This attribute specifies the (outer) label for the downstream MPLS tunnel. If the MPLS tunnel is
+//			upstream only, this attribute should be set to 0. (R, W, setbycreate) (mandatory for double-
+//			labelled case) (4 bytes)
 //
 //		Mpls Tunnel Tc
+//			This attribute specifies the TC value of the upstream MPLS tunnel. If the MPLS tunnel is
+//			downstream only, this attribute should be set to 0. (R, W, setbycreate) (mandatory for double
+//			MPLS labelled case) (1 byte)
+//
 //			NOTE 2 - The TC field was previously known as EXP. Refer to [bIETF-RFC-5462].
 //
 //		Pseudowire Type
+//			This attribute specifies the emulated service to be carried over this PW. The values are from
+//			[IETF RFC 4446].
+//
+//			2	ATM AAL5 SDU VCC transport
+//
+//			3	ATM transparent cell transport
+//
+//			5	Ethernet
+//
+//			9	ATM n-to-one VCC cell transport
+//
+//			10	ATM n-to-one VPC cell transport
+//
+//			12	ATM one-to-one VCC cell mode
+//
+//			13	ATM one-to-one VPC cell mode
+//
+//			14	ATM AAL5 PDU VCC transport
+//
+//			All other values are reserved.
+//
 //			(R, W, setbycreate) (mandatory) (2 bytes)
 //
 //		Pseudowire Control Word Preference
-//			Pseudowire control word preference: When set to true, this Boolean attribute specifies that a
-//			control word is to be sent with each packet. Some PW types mandate the use of a control word in
-//			any event. In such cases, the value configured for this attribute has no effect on the presence
-//			of the control word. (R, W, setbycreate) (optional) (1 byte)
+//			When set to true, this Boolean attribute specifies that a control word is to be sent with each
+//			packet. Some PW types mandate the use of a control word in any event. In such cases, the value
+//			configured for this attribute has no effect on the presence of the control word. (R, W,
+//			setbycreate) (optional) (1 byte)
 //
 //		Administrative State
-//			Administrative state: This attribute locks (1) and unlocks (0) the functions performed by the
-//			MPLS pseudowire TP. Administrative state is further described in clause-A.1.6. (R,-W) (optional)
-//			(1-byte)
+//			This attribute locks (1) and unlocks (0) the functions performed by the MPLS pseudowire TP.
+//			Administrative state is further described in clause-A.1.6. (R,-W) (optional) (1-byte)
 //
 //		Operational State
-//			Operational state: This attribute reports whether the ME is currently capable of performing its
-//			function. Valid values are enabled (0) and disabled (1). (R) (optional) (1-byte)
+//			This attribute reports whether the ME is currently capable of performing its function. Valid
+//			values are enabled (0) and disabled (1). (R) (optional) (1-byte)
 //
 type MplsPseudowireTerminationPoint struct {
 	ManagedEntityDefinition
diff --git a/generated/multicastgeminterworkingterminationpoint.go b/generated/multicastgeminterworkingterminationpoint.go
index 2fda7ab..fd85a10 100644
--- a/generated/multicastgeminterworkingterminationpoint.go
+++ b/generated/multicastgeminterworkingterminationpoint.go
@@ -27,11 +27,11 @@
 
 // MulticastGemInterworkingTerminationPointClassID is the 16-bit ID for the OMCI
 // Managed entity Multicast GEM interworking termination point
-const MulticastGemInterworkingTerminationPointClassID ClassID = ClassID(281)
+const MulticastGemInterworkingTerminationPointClassID = ClassID(281) // 0x0119
 
 var multicastgeminterworkingterminationpointBME *ManagedEntityDefinition
 
-// MulticastGemInterworkingTerminationPoint (class ID #281)
+// MulticastGemInterworkingTerminationPoint (Class ID: #281 / 0x0119)
 //	An instance of this ME represents a point in a G-PON ONU where a multicast service interworks
 //	with the GEM layer. At this point, a multicast bit stream is reconstructed from GEM packets.
 //
@@ -88,46 +88,98 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The value 0xFFFF
-//			is reserved. (R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. The value 0xFFFF is reserved. (R,
+//			setbycreate) (mandatory) (2-bytes)
 //
 //		Gem Port Network Ctp Connectivity Pointer
-//			GEM port network CTP connectivity pointer: This attribute points to an instance of the GEM port
-//			network CTP that is associated with this multicast GEM IW TP. (R,-W, setbycreate) (mandatory)
-//			(2-bytes)
+//			This attribute points to an instance of the GEM port network CTP that is associated with this
+//			multicast GEM IW TP. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Interworking Option
+//			3	Reserved
+//
+//			5	IEEE 802.1p mapper
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
+//			This attribute identifies the type of non-GEM function that is being interworked. The option can
+//			be as follows.
+//
+//			0	This value is a "no-op" or "don't care". It should be used when the multicast GEM IW TP is
+//			associated with several functions of different types. It can optionally be used in all cases,
+//			since the necessary information is available elsewhere. The previous code points are retained
+//			for backward compatibility:
+//
+//			1	MAC bridged LAN
+//
 //		Service Profile Pointer
-//			Service profile pointer: This attribute is set to 0 and not used. For backward compatibility, it
-//			may also be set to point to a MAC bridge service profile or IEEE 802.1p mapper service profile.
-//			(R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute is set to 0 and not used. For backward compatibility, it may also be set to point
+//			to a MAC bridge service profile or IEEE 802.1p mapper service profile. (R,-W, setbycreate)
+//			(mandatory) (2-bytes)
 //
 //		Not Used 1
-//			Not used 1:	This attribute is set to 0 and not used. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute is set to 0 and not used. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Pptp Counter
-//			PPTP counter: This attribute represents the number of instances of PPTP MEs associated with this
-//			instance of the multicast GEM IW TP. This attribute conveys no information that is not available
-//			elsewhere; it may be set to 0xFF and not used. (R) (optional) (1-byte)
+//			This attribute represents the number of instances of PPTP MEs associated with this instance of
+//			the multicast GEM IW TP. This attribute conveys no information that is not available elsewhere;
+//			it may be set to 0xFF and not used. (R) (optional) (1-byte)
 //
 //		Operational State
-//			Operational state: This attribute indicates whether the ME is capable of performing its
-//			function. Valid values are enabled (0) and disabled (1). (R) (optional) (1-byte)
+//			This attribute indicates whether the ME is capable of performing its function. Valid values are
+//			enabled (0) and disabled (1). (R) (optional) (1-byte)
 //
 //		Gal Profile Pointer
-//			GAL profile pointer: This attribute is set to 0 and not used. For backward compatibility, it may
-//			also be set to point to a GAL Ethernet profile. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute is set to 0 and not used. For backward compatibility, it may also be set to point
+//			to a GAL Ethernet profile. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Not Used 2
-//			Not used 2:	This attribute is set to 0 and not used. (R,-W, setbycreate) (mandatory) (1-byte)
+//			This attribute is set to 0 and not used. (R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Ipv4 Multicast Address Table
-//			IPv4 multicast address table: This attribute maps IP multicast addresses to PON layer addresses.
-//			Each entry contains the following.
+//			This attribute maps IP multicast addresses to PON layer addresses. Each entry contains the
+//			following.
+//
+//			GEM port-ID		2-bytes
+//
+//			Secondary key		2-bytes
+//
+//			IP multicast DA range start		4-bytes
+//
+//			IP multicast DA range stop		4-bytes
+//
+//			The first four bytes of each entry are treated as a key into the list. The secondary key allows
+//			the table to contain more than a single range for a given GEM port.
+//
+//			A set action to a particular value overwrites any existing entry with the same first four bytes.
+//			If the last eight bytes of a set command are all zero, that entry is deleted from the list, as
+//			the IP address 0.0.0.0 is not valid.
+//
+//			(R,-W) (mandatory) (12N bytes, where N is the number of entries in the list.)
 //
 //		Ipv6 Multicast Address Table
+//			This attribute maps IPv6 multicast DAs to PON layer addresses. Each entry contains:
+//
+//			GEM port-ID	2-bytes
+//
+//			Secondary key	2-bytes
+//
+//			Least significant bytes,
+//
+//			IP multicast DA range start	4-bytes
+//
+//			Least significant bytes,
+//
+//			IP multicast DA range stop	4-bytes
+//
+//			Most significant bytes, IP DA	12-bytes
+//
+//			The first four bytes of each entry are treated as a key into the list. The secondary key allows
+//			the table to contain more than a single range for a given GEM port.
+//
+//			A set action to a particular value overwrites any existing entry with the same first four bytes.
+//			If the last 20 bytes of a set command are all zero, that entry is deleted from the list.
+//
 //			(R,-W) (optional) (24N bytes, where N is the number of entries in the list.)
 //
 type MulticastGemInterworkingTerminationPoint struct {
diff --git a/generated/multicastoperationsprofile.go b/generated/multicastoperationsprofile.go
new file mode 100644
index 0000000..9db7284
--- /dev/null
+++ b/generated/multicastoperationsprofile.go
@@ -0,0 +1,280 @@
+/*
+ * 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.
+ */
+/*
+ * NOTE: This file was generated, manual edits will be overwritten!
+ *
+ * Generated by 'goCodeGenerator.py':
+ *              https://github.com/cboling/OMCI-parser/README.md
+ */
+
+package generated
+
+import "github.com/deckarep/golang-set"
+
+// MulticastOperationsProfileClassID is the 16-bit ID for the OMCI
+// Managed entity Multicast operations profile
+const MulticastOperationsProfileClassID = ClassID(309) // 0x0135
+
+var multicastoperationsprofileBME *ManagedEntityDefinition
+
+// MulticastOperationsProfile (Class ID: #309 / 0x0135)
+//	This ME expresses multicast policy. A multi-dwelling unit ONU may have several such policies,
+//	which are linked to subscribers as required. Some of the attributes configure IGMP snooping and
+//	proxy parameters if the defaults do not suffice, as described in [IETF-RFC-2236], [IETF-RFC
+//	3376], [IETF RFC 3810] and [IETF RFC 5519]. Instances of this ME are created and deleted by the
+//	OLT.
+//
+//	Relationships
+//		An instance of this ME may be associated with zero or more instances of the multicast subscriber
+//		config info ME.
+//
+//	Attributes
+//		Managed Entity Id
+//			This attribute uniquely identifies each instance of this ME. The values 0 and 0xFFFF are
+//			reserved. (R, setbycreate) (mandatory) (2-bytes)
+//
+//		Igmp Version
+//			This attribute specifies the version of IGMP to be supported. Support of a given version implies
+//			compatible support of previous versions. If the ONU cannot support the version requested, it
+//			should deny an attempt to set the attribute. (R,W, set-by-create) (mandatory) (1 byte)
+//
+//			1	IGMP version 1 (deprecated)
+//
+//			2	IGMP version 2
+//
+//			3	IGMP version 3
+//
+//			16	MLD version 1
+//
+//			17	MLD version 2
+//
+//			Other values are reserved.
+//
+//		Igmp Function
+//			This attribute enables an IGMP function. The value 0 specifies transparent IGMP snooping only.
+//			The value 1 specifies snooping with proxy reporting (SPR); the value 2 specifies IGMP proxy. The
+//			function must be consistent with the capabilities specified by the other IGMP configuration
+//			attributes. (R,W, setbycreate) (mandatory) (1-byte)
+//
+//		Immediate Leave
+//			This Boolean attribute controls the immediate leave function. The value false disables immediate
+//			leave; true enables immediate leave. (R,W, setbycreate) (mandatory) (1-byte)
+//
+//		Upstream Igmp Tci
+//			Under control of the upstream IGMP tag control attribute, the upstream IGMP TCI attribute
+//			defines a VLAN ID and P-bits to add to upstream IGMP messages. (R,-W, setbycreate) (optional)
+//			(2-bytes)
+//
+//		Upstream Igmp Tag Control
+//			2	Replace the entire TCI (VLAN ID plus P bits) on upstream IGMP/MLD traffic. The new tag is
+//			specified by the upstream IGMP/MLD TCI attribute. If the received IGMP/MLD traffic is untagged,
+//			an add operation is performed.
+//
+//			3	Replace only the VLAN ID on upstream IGMP/MLD traffic, retaining the original DEI and P bits.
+//			The new VLAN ID is specified by the VLAN ID field of the upstream IGMP TCI attribute. If the
+//			received IGMP/MLD traffic is untagged, an add operation is performed, with DEI and P bits also
+//			taken from the upstream IGMP TCI attribute.
+//
+//			Other values are reserved.
+//
+//			This attribute controls the upstream IGMP TCI attribute. If this attribute is non-zero, a
+//			possible extended VLAN tagging operation ME is ignored for upstream frames containing IGMP/MLD
+//			packets. (R,-W, setbycreate) (optional) (1-byte)
+//
+//			Value	Meaning
+//
+//			0	Pass upstream IGMP/MLD traffic transparently, neither adding, stripping nor modifying tags
+//			that may be present.
+//
+//			1	Add a VLAN tag (including P bits) to upstream IGMP/MLD traffic. The tag is specified by the
+//			upstream IGMP TCI attribute.
+//
+//		Upstream Igmp Rate
+//			This attribute limits the maximum rate of upstream IGMP traffic. Traffic in excess of this limit
+//			is silently discarded. The attribute value is specified in messages/second. The recommended
+//			default value 0 imposes no rate limit on this traffic. (R,-W, setbycreate) (optional) (4-bytes)
+//
+//		Dynamic Access Control List Table
+//			This attribute is a list that specifies one or more multicast group address ranges. Each row in
+//			the list comprises up to three row parts, where each row part is 24-bytes long. Each entry must
+//			include row part 0. The ONU may also support row parts 1-2, thus allowing the table to contain
+//			logical rows that exceed the 24-byte definition of row part 0.
+//
+//		Static Access Control List Table
+//			This attribute is a list that specifies one or more multicast group address ranges. Groups
+//			defined in this list are multicast on the associated UNI(s) unconditionally, i.e., without the
+//			need for an IGMP join. The bandwidth of static multicast groups is not included in the current
+//			multicast bandwidth measurement maintained by the multicast subscriber monitor ME. If a join
+//			message is always expected, this table may be empty. Table entries have the same format as those
+//			in the dynamic access control list table. The preview fields are not meaningful. (R,-W)
+//			(mandatory) (each row part: 24 bytes)
+//
+//		Lost Groups List Table
+//			This attribute is a list of groups from the dynamic access control list table for which there is
+//			an active join, but no downstream flow is present, possibly because of source failure, but also
+//			possibly because of misconfiguration somewhere upstream. Be aware of possible ambiguity between
+//			overlapping service providers and IPv4/IPv6 addresses. After a join, the ONU should wait a
+//			reasonable time for upstream processing before declaring a group to be lost. Each entry is a
+//			vector of the following components:
+//
+//			-	VLAN ID, 0 if not used (2-bytes)
+//
+//			-	Source IP address, 0.0.0.0 if not used. In IPv6, this field captures only the four least
+//			significant bytes. (4-bytes)
+//
+//			-	Multicast destination IP address. In IPv6, this field captures only the four least significant
+//			bytes. (4-bytes)
+//
+//			(R) (optional) (10N bytes)
+//
+//		Robustness
+//			This attribute allows tuning for possible packet loss in the network. The recommended default
+//			value 0 causes the ONU to follow [IETF RFC 3376] to copy the robustness value from query
+//			messages originating further upstream. (R,-W, setbycreate) (optional) (1-byte)
+//
+//		Querier Ip Address
+//			This attribute specifies the IP address to be used by a proxy querier. Although it is not a
+//			legitimate IP address, the recommended default value 0.0.0.0 is legal in this case (see [b-IETF
+//			RFC 4541]). (R,-W, setbycreate) (optional) (4-bytes)
+//
+//		Query Interval
+//			This attribute specifies the interval between general queries in seconds. The value 0 specifies
+//			that the ONU uses its own default, which may or may not be the same as the recommended default
+//			of 125-s. (R,-W, set-by-create) (optional) (4-bytes)
+//
+//		Query Max Response Time
+//			This attribute is the max response time added by the proxy into general query messages directed
+//			to UNIs. It is expressed in units of 0.1-s. The value 0 specifies that the ONU uses its own
+//			default, which may or may not be the same as the recommended default of 100 (10-s). (R,-W,
+//			setby-create) (optional) (4-bytes)
+//
+//		Last Member Query Interval
+//			This attribute specifies the maximum response time inserted into group-specific queries sent to
+//			UNIs in response to group leave messages. It is also the repetition rate of [robustness]
+//			transmissions of the query. It is specified in units of 0.1-s, with a default of 10 (1-s).
+//			(R,-W) (optional) (4-bytes)
+//
+//		Unauthorized Join Request Behaviour
+//			This Boolean attribute specifies the ONU's behaviour when it receives an IGMP join request for a
+//			group that is not authorized in the dynamic address control list table, or an IGMPv3 membership
+//			report for groups, none of which are authorized in the dynamic ACL. The default value false
+//			specifies that the ONU silently discard the IGMP request; the value true specifies that the ONU
+//			forwards the request upstream. The ONU does not attempt to honour the request for the
+//			unauthorized group(s) in either case. (R,-W) (optional) (1-byte)
+//
+//		Downstream IGMP and multicast TCI
+//			This attribute controls the downstream tagging of both the IGMP/MLD and multicast frames. If the
+//			first byte of this attribute is non-zero, a possible extended VLAN tagging operation ME is
+//			ignored for downstream IGMP/MLD and multicast frames. (R,-W, set-by-create) (optional) (3-bytes)
+//
+//			The first byte defines the control type:
+//
+//			Value	Meaning
+//
+//			0	Pass the downstream IGMP/MLD and multicast traffic transparently, neither stripping nor
+//			modifying tags that may be present.
+//
+//			1	Strip the outer VLAN tag (including P bits) from the downstream IGMP/MLD and multicast
+//			traffic.
+//
+//			2	Add a tag on to the downstream IGMP/MLD and multicast traffic. The new tag is specified by the
+//			second and third bytes of this attribute.
+//
+//			3	Replace the tag on the downstream IGMP/MLD and multicast traffic. The new tag is specified by
+//			the second and third bytes of this attribute.
+//
+//			4	Replace only the VLAN ID on the downstream IGMP/MLD and multicast traffic, retaining the
+//			original DEI and P bits. The new VLAN ID is specified by the VLAN ID field of the second and
+//			third bytes of this attribute.
+//
+//			5	Add a tag on to the downstream IGMP/MLD and multicast traffic. The new tag is specified by the
+//			VID (UNI) field of the multicast service package table row of the multicast subscriber config
+//			info ME that is associated with this profile. If the VID (UNI) field is unspecified (0xFFFF) or
+//			specifies untagged traffic, the new tag is specified by the second and third bytes of this
+//			attribute.
+//
+//			6	Replace the tag on the downstream IGMP/MLD and multicast traffic. The new tag is specified by
+//			the VID (UNI) field of the multicast service package table row of the multicast subscriber
+//			config info ME that is associated with this profile. If the VID (UNI) field specifies untagged
+//			traffic, the outer VLAN tag (including P bits) is stripped from the downstream IGMP/MLD and
+//			multicast traffic. If the value of the VID (UNI) is unspecified (0xFFFF), the new tag is
+//			specified by the second and third bytes of this attribute.
+//
+//			7	Replace only the VID on the downstream IGMP/MLD and multicast traffic, retaining the original
+//			DEI and P bits. The new VLAN ID is specified by the VID (UNI) field of the multicast service
+//			package table row of the multicast subscriber config info ME that is associated with this
+//			profile. If the VID (UNI) field specifies untagged traffic, the outer VLAN tag (including P
+//			bits) is stripped from the downstream IGMP/MLD and multicast traffic. If the value of the VID
+//			(UNI) is unspecified (0xFFFF), the new tag is specified by the second and third bytes of this
+//			attribute.
+//
+//			Other values are reserved.
+//
+//			The second and third bytes define the TCI (VLAN ID and P bits) to be applied on the downstream
+//			IGMP/MLD and multicast streams in case the replace or add option is selected.
+//
+type MulticastOperationsProfile struct {
+	ManagedEntityDefinition
+	Attributes AttributeValueMap
+}
+
+func init() {
+	multicastoperationsprofileBME = &ManagedEntityDefinition{
+		Name:    "MulticastOperationsProfile",
+		ClassID: 309,
+		MessageTypes: mapset.NewSetWith(
+			Create,
+			Delete,
+			Get,
+			GetNext,
+			Set,
+			SetTable,
+		),
+		AllowedAttributeMask: 0xffff,
+		AttributeDefinitions: AttributeDefinitionMap{
+			0:  Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read, SetByCreate), false, false, false, 0),
+			1:  ByteField("IgmpVersion", EnumerationAttributeType, 0x8000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 1),
+			2:  ByteField("IgmpFunction", EnumerationAttributeType, 0x4000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 2),
+			3:  ByteField("ImmediateLeave", EnumerationAttributeType, 0x2000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 3),
+			4:  Uint16Field("UpstreamIgmpTci", UnsignedIntegerAttributeType, 0x1000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, true, false, 4),
+			5:  ByteField("UpstreamIgmpTagControl", UnsignedIntegerAttributeType, 0x0800, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, true, false, 5),
+			6:  Uint32Field("UpstreamIgmpRate", UnsignedIntegerAttributeType, 0x0400, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, true, false, 6),
+			7:  TableField("DynamicAccessControlListTable", TableAttributeType, 0x0200, TableInfo{nil, 24}, mapset.NewSetWith(Read, Write), false, false, false, 7),
+			8:  TableField("StaticAccessControlListTable", TableAttributeType, 0x0100, TableInfo{nil, 24}, mapset.NewSetWith(Read, Write), false, false, false, 8),
+			9:  TableField("LostGroupsListTable", TableAttributeType, 0x0080, TableInfo{nil, 10}, mapset.NewSetWith(Read), false, true, false, 9),
+			10: ByteField("Robustness", UnsignedIntegerAttributeType, 0x0040, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, true, false, 10),
+			11: Uint32Field("QuerierIpAddress", UnsignedIntegerAttributeType, 0x0020, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, true, false, 11),
+			12: Uint32Field("QueryInterval", UnsignedIntegerAttributeType, 0x0010, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, true, false, 12),
+			13: Uint32Field("QueryMaxResponseTime", UnsignedIntegerAttributeType, 0x0008, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, true, false, 13),
+			14: Uint32Field("LastMemberQueryInterval", UnsignedIntegerAttributeType, 0x0004, 0, mapset.NewSetWith(Read, Write), false, true, false, 14),
+			15: ByteField("UnauthorizedJoinRequestBehaviour", UnsignedIntegerAttributeType, 0x0002, 0, mapset.NewSetWith(Read, Write), false, true, false, 15),
+			16: MultiByteField("DownstreamIgmpAndMulticastTci", OctetsAttributeType, 0x0001, 3, toOctets("AAAA"), mapset.NewSetWith(Read, SetByCreate, Write), false, true, false, 16),
+		},
+		Access:  CreatedByOlt,
+		Support: UnknownSupport,
+		Alarms: AlarmMap{
+			0: "Lost multicast group",
+		},
+	}
+}
+
+// NewMulticastOperationsProfile (class ID 309) creates the basic
+// Managed Entity definition that is used to validate an ME of this type that
+// is received from or transmitted to the OMCC.
+func NewMulticastOperationsProfile(params ...ParamData) (*ManagedEntity, OmciErrors) {
+	return NewManagedEntity(*multicastoperationsprofileBME, params...)
+}
diff --git a/generated/multicastoperationsprofileframe.go b/generated/multicastoperationsprofileframe.go
deleted file mode 100644
index 6204894..0000000
--- a/generated/multicastoperationsprofileframe.go
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.
- */
-/*
-* NOTE: This file was hand coded (not generated by omci-parser) due to complexity
-*       of the ME's entry in the G.988 (11/2017) specification.
- */
-package generated
-
-import "github.com/deckarep/golang-set"
-
-const MulticastOperationsProfileClassID ClassID = ClassID(309)
-
-var multicastoperationsprofileME *ManagedEntityDefinition
-
-type MulticastOperationsProfile struct {
-	ManagedEntityDefinition
-	Attributes AttributeValueMap
-}
-
-func init() {
-	multicastoperationsprofileME = &ManagedEntityDefinition{
-		Name:    "MulticastOperationsProfile",
-		ClassID: 309,
-		MessageTypes: mapset.NewSetWith(
-			Create,
-			Delete,
-			Get,
-			Set,
-			GetNext,
-		),
-		AllowedAttributeMask: 0xffff,
-		AttributeDefinitions: AttributeDefinitionMap{
-			0:  Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read, SetByCreate), false, false, false, 0),
-			1:  ByteField("IgmpVersion", EnumerationAttributeType, 0x8000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 1),
-			2:  ByteField("IgmpFunction", EnumerationAttributeType, 0x4000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 2),
-			3:  ByteField("ImmediateLeave", EnumerationAttributeType, 0x2000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 3),
-			4:  Uint16Field("USIgmpTci", UnsignedIntegerAttributeType, 0x1000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, true, false, 4),
-			5:  ByteField("USIgmpTagCtrl", EnumerationAttributeType, 0x0800, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, true, false, 5),
-			6:  Uint32Field("USIgmpRate", UnsignedIntegerAttributeType, 0x0400, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, true, false, 6),
-			7:  TableField("DynamicAccessControlListTable", TableAttributeType, 0x0200, TableInfo{nil, 24}, mapset.NewSetWith(Read, Write), false, false, false, 7),
-			8:  TableField("StaticAccessControlListTable", TableAttributeType, 0x0100, TableInfo{nil, 24}, mapset.NewSetWith(Read, Write), false, true, false, 8),
-			9:  TableField("LostGroupsListTable", TableAttributeType, 0x0080, TableInfo{nil, 10}, mapset.NewSetWith(Read), false, true, false, 9),
-			10: ByteField("Robustness", UnsignedIntegerAttributeType, 0x0040, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, true, false, 10),
-			11: Uint32Field("QuerierIp", UnsignedIntegerAttributeType, 0x0020, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, true, false, 11),
-			12: Uint32Field("QueryInterval", UnsignedIntegerAttributeType, 0x0010, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, true, false, 12),
-			13: Uint32Field("QuerierMaxResponseTime", UnsignedIntegerAttributeType, 0x0008, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, true, false, 13),
-			14: Uint32Field("LastMemberResponseTime", UnsignedIntegerAttributeType, 0x0004, 0, mapset.NewSetWith(Read, Write), false, true, false, 14),
-			15: ByteField("UnauthorizedJoinBehaviour", UnsignedIntegerAttributeType, 0x0002, 0, mapset.NewSetWith(Read, Write), false, true, false, 15),
-			16: MultiByteField("DSIgmpMcastTci", OctetsAttributeType, 0x0001, 3, toOctets("AAAA"), mapset.NewSetWith(Read, SetByCreate, Write), false, true, false, 16),
-		},
-		Access:  CreatedByOlt,
-		Support: UnknownSupport,
-	}
-}
-
-// NewMulticastOperationsProfilePoint (class ID 309) creates the basic
-// Managed Entity definition that is used to validate an ME of this type that
-// is received from or transmitted to the OMCC.
-func NewMulticastOperationsProfile(params ...ParamData) (*ManagedEntity, OmciErrors) {
-	return NewManagedEntity(*multicastoperationsprofileME, params...)
-}
diff --git a/generated/multicastsubscriberconfiginfo.go b/generated/multicastsubscriberconfiginfo.go
index b83883b..1932b6b 100644
--- a/generated/multicastsubscriberconfiginfo.go
+++ b/generated/multicastsubscriberconfiginfo.go
@@ -27,11 +27,11 @@
 
 // MulticastSubscriberConfigInfoClassID is the 16-bit ID for the OMCI
 // Managed entity Multicast subscriber config info
-const MulticastSubscriberConfigInfoClassID ClassID = ClassID(310)
+const MulticastSubscriberConfigInfoClassID = ClassID(310) // 0x0136
 
 var multicastsubscriberconfiginfoBME *ManagedEntityDefinition
 
-// MulticastSubscriberConfigInfo (class ID #310)
+// MulticastSubscriberConfigInfo (Class ID: #310 / 0x0136)
 //	This ME organizes data associated with multicast management at subscriber ports of IEEE-802.1
 //	bridges, including IEEE-802.1p mappers when the provisioning model is mapper-based rather than
 //	bridge-based. Instances of this ME are created and deleted by the OLT. Because of backward
@@ -51,43 +51,118 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the MAC bridge port configuration
-//			data or IEEE-802.1p mapper ME. (R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the MAC bridge port configuration data or IEEE-802.1p mapper
+//			ME. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Me Type
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
+//			This attribute indicates the type of the ME implicitly linked by the ME ID attribute.
+//
+//			0	MAC bridge port config data
+//
+//			1	IEEE-802.1p mapper service profile
+//
 //		Multicast Operations Profile Pointer
-//			Multicast operations profile pointer: This attribute points to an instance of the multicast
-//			operations profile. This attribute is ignored by the ONU if a non-empty multicast service
-//			package table attribute is present. (R,W, set-by-create) (mandatory) (2 bytes)
+//			This attribute points to an instance of the multicast operations profile. This attribute is
+//			ignored by the ONU if a non-empty multicast service package table attribute is present. (R,W,
+//			set-by-create) (mandatory) (2 bytes)
 //
 //		Max Simultaneous Groups
-//			Max simultaneous groups: This attribute specifies the maximum number of dynamic multicast groups
-//			that may be replicated to the client port at any one time. The recommended default value 0
-//			specifies that no administrative limit is to be imposed. (R,-W, setbycreate) (optional)
-//			(2-bytes)
+//			This attribute specifies the maximum number of dynamic multicast groups that may be replicated
+//			to the client port at any one time. The recommended default value 0 specifies that no
+//			administrative limit is to be imposed. (R,-W, setbycreate) (optional) (2-bytes)
 //
 //		Max Multicast Bandwidth
-//			Max multicast bandwidth: This attribute specifies the maximum imputed dynamic bandwidth, in
-//			bytes per second, that may be delivered to the client port at any one time. The recommended
-//			default value 0 specifies that no administrative limit is to be imposed. (R,-W, setbycreate)
-//			(optional) (4-bytes)
+//			This attribute specifies the maximum imputed dynamic bandwidth, in bytes per second, that may be
+//			delivered to the client port at any one time. The recommended default value 0 specifies that no
+//			administrative limit is to be imposed. (R,-W, setbycreate) (optional) (4-bytes)
 //
 //		Bandwidth Enforcement
-//			Bandwidth enforcement: The recommended default value of this Boolean attribute is false, and
-//			specifies that attempts to exceed the max multicast bandwidth be counted but honoured. The value
-//			true specifies that such attempts be counted and denied. The imputed bandwidth value is taken
-//			from the dynamic access control list table, both for a new join request and for pre-existing
-//			groups. (R,-W, setbycreate) (optional) (1-byte)
+//			The recommended default value of this Boolean attribute is false, and specifies that attempts to
+//			exceed the max multicast bandwidth be counted but honoured. The value true specifies that such
+//			attempts be counted and denied. The imputed bandwidth value is taken from the dynamic access
+//			control list table, both for a new join request and for pre-existing groups. (R,-W, setbycreate)
+//			(optional) (1-byte)
 //
 //		Multicast Service Package Table
+//			This attribute is a list that specifies one or more multicast service packages. When the ONU
+//			receives an IGMP/MLD join request, it searches the multicast service package table in row key
+//			order, matching the VID (UNI) field (several rows can share the same VID). For each VID (UNI)
+//			match, the multicast operations profile pointer is used to access the ME that contains the
+//			attributes associated with the service package. The search stops when all requested multicast
+//			groups have been found and dealt with.
+//
+//			Each list entry is a vector of six components as follow.
+//
+//			-	Table control (2-bytes)
+//
+//			The first 2-bytes of each entry contain a key into the table. It is the responsibility of the
+//			OLT to assign and track table keys and content. Since row keys are created by the OLT, they may
+//			be densely or sparsely packed.
+//
+//			The two MSBs of this field determine the meaning of a set operation. These bits are returned as
+//			00 during get next operations.
+//
+//			Bits 14..11 are reserved. Bits 10..1 are the row key itself.
+//
+//			-	VID (UNI). The value in this field is compared with the VID of upstream IGMP/MLD messages, and
+//			is used to decide whether to honour a join request. (2 bytes)
+//
+//			Values:
+//
+//			0..4095 - Matched against the VID of the IGMP/MLD message. 0 indicates a priority-tagged
+//			message, whose P bits are ignored.
+//
+//			4096 - Matches untagged IGMP/MLD messages only.
+//
+//			4097 - Matches tagged messages only, but ignores the value of the VID.
+//
+//			0xFFFF - Unspecified.
+//
+//			The VID (UNI) comparison occurs prior to any action defined by the upstream IGMP tag control
+//			attribute in an associated multicast operations profile (or alternatively, before any
+//			modification by a possible (extended) VLAN tagging operation configuration data ME).
+//
+//			-	Max simultaneous groups. This field specifies the maximum number of dynamic multicast groups
+//			that may be replicated to the client port at any one time, for the multicast service package
+//			that is associated with this row. The value 0 specifies that no administrative limit is to be
+//			imposed. (2-bytes)
+//
+//			-	Max multicast bandwidth. This field specifies the maximum imputed dynamic bandwidth, in bytes
+//			per second, that may be delivered to the client port at any one time, for the multicast service
+//			package that is associated with this row. The value 0 specifies that no administrative limit is
+//			to be imposed. (4-bytes)
+//
+//			NOTE - The port is also constrained by the global max simultaneous groups and max multicast
+//			bandwidth attributes of the multicast subscriber config info ME.
+//
+//			-	Multicast operations profile pointer. This field contains the ME ID of the multicast
+//			operations profile ME associated with this service package. (2 bytes)
+//
+//			-	Reserved (8 bytes)
+//
 //			(R,-W) (optional) (20N bytes, where N is the number of entries in the table)
 //
 //		Allowed Preview Groups Table
 //			Each list entry begins with a table control field:
 //
+//			This attribute is a list that specifies the preview groups that are currently allowed for the
+//			UNI associated with this ME. It is intended to support paid viewing of a multicast group that
+//			may or may not have been previewed.
+//
+//			When an IGMP/MLD join request is received, the order of search precedence is as follows.
+//
+//			1. Multicast operations profile(s), fully authorized groups
+//
+//			2. This attribute, the allowed preview groups table
+//
+//			3. Multicast operations profile(s), preview-only groups
+//
+//			If the first match is a group listed in this attribute, the ONU forwards the group to the UNI
+//			until the group is removed from this list or until the subscriber leaves the group.
+//
 type MulticastSubscriberConfigInfo struct {
 	ManagedEntityDefinition
 	Attributes AttributeValueMap
diff --git a/generated/multicastsubscribermonitor.go b/generated/multicastsubscribermonitor.go
index b95256e..a43d342 100644
--- a/generated/multicastsubscribermonitor.go
+++ b/generated/multicastsubscribermonitor.go
@@ -27,11 +27,11 @@
 
 // MulticastSubscriberMonitorClassID is the 16-bit ID for the OMCI
 // Managed entity Multicast subscriber monitor
-const MulticastSubscriberMonitorClassID ClassID = ClassID(311)
+const MulticastSubscriberMonitorClassID = ClassID(311) // 0x0137
 
 var multicastsubscribermonitorBME *ManagedEntityDefinition
 
-// MulticastSubscriberMonitor (class ID #311)
+// MulticastSubscriberMonitor (Class ID: #311 / 0x0137)
 //	This ME provides the current status of each port with respect to its multicast subscriptions. It
 //	may be useful for status monitoring or debugging purposes. The status table includes all dynamic
 //	groups currently subscribed by the port.
@@ -42,34 +42,78 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the MAC bridge port configuration
-//			data or IEEE-802.1p mapper ME. (R,-setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the MAC bridge port configuration data or IEEE-802.1p mapper
+//			ME. (R,-setbycreate) (mandatory) (2-bytes)
 //
 //		Me Type
+//			This attribute indicates the type of the ME implicitly linked by the ME ID attribute.
+//
+//			0	MAC bridge port config data
+//
+//			1	IEEE-802.1p mapper service profile
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Current Multicast Bandwidth
-//			Current multicast bandwidth: This attribute is the ONU's (BE) estimate of the actual bandwidth
-//			currently being delivered to this particular MAC bridge port over all dynamic multicast groups.
-//			(R) (optional) (4-bytes)
+//			This attribute is the ONU's (BE) estimate of the actual bandwidth currently being delivered to
+//			this particular MAC bridge port over all dynamic multicast groups. (R) (optional) (4-bytes)
 //
 //		Join Messages Counter
-//			Join messages counter: This attribute counts the number of times the corresponding subscriber
-//			sent a join message that was accepted. When full, the counter rolls over to 0. (R) (optional)
-//			(4-bytes)
+//			This attribute counts the number of times the corresponding subscriber sent a join message that
+//			was accepted. When full, the counter rolls over to 0. (R) (optional) (4-bytes)
 //
 //		Bandwidth Exceeded Counter
-//			Bandwidth exceeded counter: This attribute counts the number of join messages that did exceed,
-//			or would have exceeded, the max multicast bandwidth, whether accepted or denied. When full, the
-//			counter rolls over to 0. (R) (optional) (4-bytes)
+//			This attribute counts the number of join messages that did exceed, or would have exceeded, the
+//			max multicast bandwidth, whether accepted or denied. When full, the counter rolls over to 0. (R)
+//			(optional) (4-bytes)
 //
 //		Ipv4 Active Group List Table
+//			This attribute lists the groups from one of the related dynamic access control list tables or
+//			the allowed preview groups table that are currently being actively forwarded, along with the
+//			actual bandwidth of each. If a join has been recognized from more than one IPv4 source address
+//			for a given group on this UNI, there will be one table entry for each. Each table entry has the
+//			following form.
+//
+//			-	VLAN ID, 0 if not used (2-bytes)
+//
+//			-	Source IP address, 0.0.0.0 if not used (4-bytes)
+//
+//			-	Multicast destination IP address (4-bytes)
+//
+//			-	Best efforts actual bandwidth estimate, bytes per second (4-bytes)
+//
+//			-	Client (set-top box) IP address, i.e., the IP address of the device currently joined (4-bytes)
+//
+//			-	Time since the most recent join of this client to the IP channel, in seconds (4-bytes)
+//
+//			-	Reserved (2-bytes)
+//
 //			(R) (mandatory) (24N bytes)
 //
 //		Ipv6 Active Group List Table
+//			-	Time since the most recent join of this client to the IP channel, in seconds (4-bytes)
+//
 //			(R) (optional) (58N bytes)
 //
+//			This attribute lists the groups from one of the related dynamic access control list tables or
+//			the allowed preview groups table that are currently being actively forwarded, along with the
+//			actual bandwidth of each. If a join has been recognized from more than one IPv6 source address
+//			for a given group on this UNI, there will be one table entry for each. In mixed IPv4-IPv6
+//			scenarios, it is possible that some fields might be IPv4, in which case their 12 most
+//			significant bytes of the given field are set to zero. Each table entry has the form:
+//
+//			-	VLAN ID, 0 if not used (2-bytes)
+//
+//			-	Source IP address, 0 if not used (16-bytes)
+//
+//			-	Multicast destination IP address (16-bytes)
+//
+//			-	Best efforts actual bandwidth estimate, bytes per second (4-bytes)
+//
+//			-	Client (set-top box) IP address, i.e., the IP address of the device currently joined
+//			(16-bytes)
+//
 type MulticastSubscriberMonitor struct {
 	ManagedEntityDefinition
 	Attributes AttributeValueMap
diff --git a/generated/networkaddress.go b/generated/networkaddress.go
index b5d755d..e965db7 100644
--- a/generated/networkaddress.go
+++ b/generated/networkaddress.go
@@ -27,11 +27,11 @@
 
 // NetworkAddressClassID is the 16-bit ID for the OMCI
 // Managed entity Network address
-const NetworkAddressClassID ClassID = ClassID(137)
+const NetworkAddressClassID = ClassID(137) // 0x0089
 
 var networkaddressBME *ManagedEntityDefinition
 
-// NetworkAddress (class ID #137)
+// NetworkAddress (Class ID: #137 / 0x0089)
 //	The network address ME associates a network address with security methods required to access a
 //	server. It is conditionally required for ONUs that support VoIP services. The address may take
 //	the form of a URL, a fully qualified path or IP address represented as an ACII string.
@@ -46,22 +46,22 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Instances of
-//			this ME created autonomously by the ONU have IDs in the range 0..0x7FFF. Instances created by
-//			the OLT have IDs in the range 0x8000..0xFFFE. The value 0xFFFF is reserved. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Instances of this ME created
+//			autonomously by the ONU have IDs in the range 0..0x7FFF. Instances created by the OLT have IDs
+//			in the range 0x8000..0xFFFE. The value 0xFFFF is reserved. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Security Pointer
-//			Security pointer: This attribute points to an authentication security method ME. The
-//			authentication security method indicates the username and password to be used when retrieving
-//			the network address indicated by this ME. A null pointer indicates that security attributes are
-//			not defined for this network address. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute points to an authentication security method ME. The authentication security
+//			method indicates the username and password to be used when retrieving the network address
+//			indicated by this ME. A null pointer indicates that security attributes are not defined for this
+//			network address. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Address Pointer
-//			Address pointer: This attribute points to the large string ME that contains the network address.
-//			It may contain a fully qualified domain name, URI or IP address. The URI may also contain a port
-//			identifier (e.g., "x.y.z.com:5060"). A null pointer indicates that no network address is
-//			defined. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute points to the large string ME that contains the network address. It may contain a
+//			fully qualified domain name, URI or IP address. The URI may also contain a port identifier
+//			(e.g., "x.y.z.com:5060"). A null pointer indicates that no network address is defined. (R,-W,
+//			setbycreate) (mandatory) (2-bytes)
 //
 type NetworkAddress struct {
 	ManagedEntityDefinition
diff --git a/generated/networkdialplantable.go b/generated/networkdialplantable.go
index 8a4f851..212aa55 100644
--- a/generated/networkdialplantable.go
+++ b/generated/networkdialplantable.go
@@ -27,11 +27,11 @@
 
 // NetworkDialPlanTableClassID is the 16-bit ID for the OMCI
 // Managed entity Network dial plan table
-const NetworkDialPlanTableClassID ClassID = ClassID(145)
+const NetworkDialPlanTableClassID = ClassID(145) // 0x0091
 
 var networkdialplantableBME *ManagedEntityDefinition
 
-// NetworkDialPlanTable (class ID #145)
+// NetworkDialPlanTable (Class ID: #145 / 0x0091)
 //	The network dial plan table ME is optional for ONUs providing VoIP services. This ME is used to
 //	provision dial plans from the OLT. Instances of this ME are created and deleted by the OLT. If a
 //	non-OMCI interface is used to manage SIP for VoIP, this ME is unnecessary.
@@ -41,31 +41,62 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
-//
-//		Dial Plan Number
-//			Dial plan number: This attribute indicates the current number of dial plans in the dial plan
-//			table. (R) (mandatory) (2-bytes)
-//
-//		Dial Plan Table Max Size
-//			Dial plan table max size: This attribute defines the maximum number of dial plans that can be
-//			stored in the dial plan table. (R, setbycreate) (mandatory) (2-bytes)
-//
-//		Critical Dial Timeout
-//			Critical dial timeout: This attribute defines the critical dial timeout for digit map
-//			processing, in milliseconds. The recommended default value is 4000-ms. (R,-W, setbycreate)
-//			(mandatory) (2-bytes)
-//
-//		Partial Dial Timeout
-//			Partial dial timeout: This attribute defines the partial dial timeout for digit map processing,
-//			in milliseconds. The recommended default value is 16000-ms. (R,-W, setbycreate) (mandatory)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
 //			(2-bytes)
 //
+//		Dial Plan Number
+//			This attribute indicates the current number of dial plans in the dial plan table. (R)
+//			(mandatory) (2-bytes)
+//
+//		Dial Plan Table Max Size
+//			This attribute defines the maximum number of dial plans that can be stored in the dial plan
+//			table. (R, setbycreate) (mandatory) (2-bytes)
+//
+//		Critical Dial Timeout
+//			This attribute defines the critical dial timeout for digit map processing, in milliseconds. The
+//			recommended default value is 4000-ms. (R,-W, setbycreate) (mandatory) (2-bytes)
+//
+//		Partial Dial Timeout
+//			This attribute defines the partial dial timeout for digit map processing, in milliseconds. The
+//			recommended default value is 16000-ms. (R,-W, setbycreate) (mandatory) (2-bytes)
+//
 //		Dial Plan Format
+//			This attribute defines the dial plan format standard that is supported in the ONU for VoIP.
+//			Valid values include the following.
+//
+//			0	Not defined
+//
+//			1	ITU-T H.248 format with a specific plan (table entries define the dialling plan)
+//
+//			2	NCS format [b-PKT-SP-NCS ]
+//
+//			3	Vendor-specific format
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Dial Plan Table
+//			The table is the digit map that describes the dial plans used by the VoIP service, along with
+//			fields to manage the table. An example digit map is the string,
+//
+//			(0T|00T|[1-7]xxx|8xxxxxxx|#xxxxxxx|*xx|91xxxxxxxxxx|9011x.T)
+//
+//			Each row of the table comprises the following fields:
+//
+//			Dial plan ID: The row number, a unique identifier of a dial plan within the dial plan table
+//			(1-byte).
+//
+//			Action: Remove (0) or add (1) this plan (set action). When a dial plan is being removed, the
+//			dial plan token field is not used. (1-byte).
+//
+//			Dial plan token: The definition of the dial plan itself. In the previous example, tokens include
+//			the strings "0T" and "*xx". Unused trailing bytes may be padded with nulls or ASCII spaces.
+//			(28-bytes)
+//
+//			NOTE - Due to previously ambiguous documentation, implementations may vary. For
+//			interoperability, the OLT should write table entries as documented above, while it is encouraged
+//			for the ONU to accept any characters outside the formal grammar as delimiters and to accept the
+//			concatenation of rows as a single string that defines a digit map.
+//
 //			(R,-W) (mandatory) (30 * N bytes, where N is the number of dial plans)
 //
 type NetworkDialPlanTable struct {
diff --git a/generated/octetstring.go b/generated/octetstring.go
index 09e6eb8..941761d 100644
--- a/generated/octetstring.go
+++ b/generated/octetstring.go
@@ -27,11 +27,11 @@
 
 // OctetStringClassID is the 16-bit ID for the OMCI
 // Managed entity Octet string
-const OctetStringClassID ClassID = ClassID(307)
+const OctetStringClassID = ClassID(307) // 0x0133
 
 var octetstringBME *ManagedEntityDefinition
 
-// OctetString (class ID #307)
+// OctetString (Class ID: #307 / 0x0133)
 //	The octet string is modelled on the large string ME. The large string is constrained to
 //	printable characters because it uses null as a trailing delimiter. The octet string has a length
 //	attribute and is therefore suitable for arbitrary sequences of bytes.
@@ -47,15 +47,88 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The values 0 and
-//			0xFFFF are reserved. (R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. The values 0 and 0xFFFF are
+//			reserved. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Length
-//			Length:	This attribute specifies the number of octets that comprise the sequence of octets. This
+//			This attribute specifies the number of octets that comprise the sequence of octets. This
 //			attribute defaults to 0 to indicate no octet string is defined. The maximum value of this
 //			attribute is 375 (15 parts, 25-bytes each). (R,-W) (mandatory) (2-bytes)
 //
-//		Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9, Part 10, Part 11, Part 12, Part 13, Part 14, Part 15
+//			In the following, 15 additional attributes are defined; they are identical. The octet string is
+//			simply divided into as many parts as necessary, starting at part 1 and left justified.
+//
+//		Part 1
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15:  (R,-W) (part 1 mandatory, others optional) (25-bytes * 15
+//			attributes)
+//
+//		Part 2
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15:  (R,-W) (part 1 mandatory, others optional) (25-bytes * 15
+//			attributes)
+//
+//		Part 3
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15:  (R,-W) (part 1 mandatory, others optional) (25-bytes * 15
+//			attributes)
+//
+//		Part 4
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15:  (R,-W) (part 1 mandatory, others optional) (25-bytes * 15
+//			attributes)
+//
+//		Part 5
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15:  (R,-W) (part 1 mandatory, others optional) (25-bytes * 15
+//			attributes)
+//
+//		Part 6
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15:  (R,-W) (part 1 mandatory, others optional) (25-bytes * 15
+//			attributes)
+//
+//		Part 7
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15:  (R,-W) (part 1 mandatory, others optional) (25-bytes * 15
+//			attributes)
+//
+//		Part 8
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15:  (R,-W) (part 1 mandatory, others optional) (25-bytes * 15
+//			attributes)
+//
+//		Part 9
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15:  (R,-W) (part 1 mandatory, others optional) (25-bytes * 15
+//			attributes)
+//
+//		Part 10
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15:  (R,-W) (part 1 mandatory, others optional) (25-bytes * 15
+//			attributes)
+//
+//		Part 11
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15:  (R,-W) (part 1 mandatory, others optional) (25-bytes * 15
+//			attributes)
+//
+//		Part 12
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15:  (R,-W) (part 1 mandatory, others optional) (25-bytes * 15
+//			attributes)
+//
+//		Part 13
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15:  (R,-W) (part 1 mandatory, others optional) (25-bytes * 15
+//			attributes)
+//
+//		Part 14
+//			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
+//			12, Part 13, Part 14, Part 15:  (R,-W) (part 1 mandatory, others optional) (25-bytes * 15
+//			attributes)
+//
+//		Part 15
 //			Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7, Part 8, Part 9,  Part 10, Part 11, Part
 //			12, Part 13, Part 14, Part 15:  (R,-W) (part 1 mandatory, others optional) (25-bytes * 15
 //			attributes)
@@ -75,11 +148,25 @@
 			Get,
 			Set,
 		),
-		AllowedAttributeMask: 0xc000,
+		AllowedAttributeMask: 0xffff,
 		AttributeDefinitions: AttributeDefinitionMap{
-			0: Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read, SetByCreate), false, false, false, 0),
-			1: Uint16Field("Length", UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read, Write), false, false, false, 1),
-			2: MultiByteField("Part1,Part2,Part3,Part4,Part5,Part6,Part7,Part8,Part9,Part10,Part11,Part12,Part13,Part14,Part15", OctetsAttributeType, 0x4000, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), false, false, false, 2),
+			0:  Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read, SetByCreate), false, false, false, 0),
+			1:  Uint16Field("Length", UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read, Write), false, false, false, 1),
+			2:  MultiByteField("Part1", OctetsAttributeType, 0x4000, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), false, false, false, 2),
+			3:  MultiByteField("Part2", OctetsAttributeType, 0x2000, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), false, true, false, 3),
+			4:  MultiByteField("Part3", OctetsAttributeType, 0x1000, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), false, true, false, 4),
+			5:  MultiByteField("Part4", OctetsAttributeType, 0x0800, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), false, true, false, 5),
+			6:  MultiByteField("Part5", OctetsAttributeType, 0x0400, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), false, true, false, 6),
+			7:  MultiByteField("Part6", OctetsAttributeType, 0x0200, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), false, true, false, 7),
+			8:  MultiByteField("Part7", OctetsAttributeType, 0x0100, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), false, true, false, 8),
+			9:  MultiByteField("Part8", OctetsAttributeType, 0x0080, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), false, true, false, 9),
+			10: MultiByteField("Part9", OctetsAttributeType, 0x0040, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), false, true, false, 10),
+			11: MultiByteField("Part10", OctetsAttributeType, 0x0020, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), false, true, false, 11),
+			12: MultiByteField("Part11", OctetsAttributeType, 0x0010, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), false, true, false, 12),
+			13: MultiByteField("Part12", OctetsAttributeType, 0x0008, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), false, true, false, 13),
+			14: MultiByteField("Part13", OctetsAttributeType, 0x0004, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), false, true, false, 14),
+			15: MultiByteField("Part14", OctetsAttributeType, 0x0002, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), false, true, false, 15),
+			16: MultiByteField("Part15", OctetsAttributeType, 0x0001, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read, Write), false, true, false, 16),
 		},
 		Access:  CreatedByOlt,
 		Support: UnknownSupport,
diff --git a/generated/olt-g.go b/generated/olt-g.go
index d3d3c7d..fbbff70 100644
--- a/generated/olt-g.go
+++ b/generated/olt-g.go
@@ -27,11 +27,11 @@
 
 // OltGClassID is the 16-bit ID for the OMCI
 // Managed entity OLT-G
-const OltGClassID ClassID = ClassID(131)
+const OltGClassID = ClassID(131) // 0x0083
 
 var oltgBME *ManagedEntityDefinition
 
-// OltG (class ID #131)
+// OltG (Class ID: #131 / 0x0083)
 //	This optional ME identifies the OLT to which an ONU is connected. This ME provides a way for the
 //	ONU to configure itself for operability with a particular OLT. It also provides a way for the
 //	OLT to communicate the time of day to the ONU.
@@ -46,25 +46,32 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. There is only
-//			one instance, number 0. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. There is only one instance, number
+//			0. (R) (mandatory) (2-bytes)
 //
 //		Olt Vendor Id
-//			OLT vendor ID: This attribute identifies the OLT vendor. It is the same as the four most
-//			significant bytes of an ONU serial number specified in the respective TC layer specification.
-//			Upon instantiation, this attribute comprises all spaces. (R,-W) (mandatory) (4-bytes)
+//			This attribute identifies the OLT vendor. It is the same as the four most significant bytes of
+//			an ONU serial number specified in the respective TC layer specification. Upon instantiation,
+//			this attribute comprises all spaces. (R,-W) (mandatory) (4-bytes)
 //
 //		Equipment Id
-//			Equipment ID: This attribute may be used to identify the specific type of OLT. The default value
-//			of all spaces indicates that equipment ID information is not available or applicable to the OLT
-//			being represented. (R,-W) (mandatory) (20-bytes)
+//			This attribute may be used to identify the specific type of OLT. The default value of all spaces
+//			indicates that equipment ID information is not available or applicable to the OLT being
+//			represented. (R,-W) (mandatory) (20-bytes)
 //
 //		Version
-//			Version:	This attribute identifies the version of the OLT as defined by the vendor. The default
-//			left-justified ASCII string "0" (padded with trailing nulls) indicates that version information
-//			is not available or applicable to the OLT being represented. (R,-W) (mandatory) (14-bytes)
+//			This attribute identifies the version of the OLT as defined by the vendor. The default left-
+//			justified ASCII string "0" (padded with trailing nulls) indicates that version information is
+//			not available or applicable to the OLT being represented. (R,-W) (mandatory) (14-bytes)
 //
 //		Time Of Day Information
+//			This attribute provides the information required to achieve time of day synchronization between
+//			a reference clock at the OLT and a local clock at the ONU. This attribute comprises two fields:
+//			the first field (4-bytes) is the sequence number of the specified GEM superframe. The second
+//			field (10-bytes) is TstampN as defined in clause 10.4.6 of [ITUT G.984.3], clause 13.2 of [ITUT
+//			G.987.3] and clause 13.2 of [ITU-T G.989.3], using the timestamp format of clause 5.3.3 of [IEEE
+//			1588]. The value 0 in all bytes is reserved as a null value. (R,-W) (optional) (14-bytes)
+//
 //			NOTE - In ITU-T G.987/ITU-T G.989 systems, the superframe count field of the time of day
 //			information attribute contains the 32 LSBs of the actual counter.
 //
diff --git a/generated/omci.go b/generated/omci.go
index 10318ec..77b4777 100644
--- a/generated/omci.go
+++ b/generated/omci.go
@@ -27,11 +27,11 @@
 
 // OmciClassID is the 16-bit ID for the OMCI
 // Managed entity OMCI
-const OmciClassID ClassID = ClassID(287)
+const OmciClassID = ClassID(287) // 0x011f
 
 var omciBME *ManagedEntityDefinition
 
-// Omci (class ID #287)
+// Omci (Class ID: #287 / 0x011f)
 //	This ME describes the ONU's general level of support for OMCI MEs and messages. This ME is not
 //	included in an MIB upload.
 //
@@ -40,18 +40,18 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. There is only
-//			one instance, number 0. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. There is only one instance, number
+//			0. (R) (mandatory) (2-bytes)
 //
 //		Me Type Table
-//			ME type table: This attribute lists the ME classes supported by the ONU. Each entry contains the
-//			ME class value (see Table 11.2.4-1) of an ME type. (R) (mandatory) (2 * N bytes, where N is the
-//			number of entries in the list.)
+//			This attribute lists the ME classes supported by the ONU. Each entry contains the ME class value
+//			(see Table 11.2.4-1) of an ME type. (R) (mandatory) (2 * N bytes, where N is the number of
+//			entries in the list.)
 //
 //		Message Type Table
-//			Message type table: This attribute is a list of message types (MTs) supported by the ONU. Each
-//			entry contains the MT of an OMCI message (see Table-11.2.2-1). (R) (mandatory) (M bytes, where M
-//			is the number of entries in the list.)
+//			This attribute is a list of message types (MTs) supported by the ONU. Each entry contains the MT
+//			of an OMCI message (see Table-11.2.2-1). (R) (mandatory) (M bytes, where M is the number of
+//			entries in the list.)
 //
 type Omci struct {
 	ManagedEntityDefinition
diff --git a/generated/onu-g.go b/generated/onu-g.go
index f4aacdc..04bdca0 100644
--- a/generated/onu-g.go
+++ b/generated/onu-g.go
@@ -27,11 +27,11 @@
 
 // OnuGClassID is the 16-bit ID for the OMCI
 // Managed entity ONU-G
-const OnuGClassID ClassID = ClassID(256)
+const OnuGClassID = ClassID(256) // 0x0100
 
 var onugBME *ManagedEntityDefinition
 
-// OnuG (class ID #256)
+// OnuG (Class ID: #256 / 0x0100)
 //	This ME represents the ONU as equipment. The ONU automatically creates an instance of this ME.
 //	It assigns values to read-only attributes according to data within the ONU itself.
 //
@@ -43,70 +43,113 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. There is only
-//			one instance, number 0. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. There is only one instance, number
+//			0. (R) (mandatory) (2-bytes)
 //
 //		Vendor Id
-//			Vendor ID:	This attribute identifies the vendor of the ONU. It is the same as the four most
-//			significant bytes of the ONU serial number as specified in the respective transmission
-//			convergence (TC) layer specification. (R) (mandatory) (4-bytes)
+//			This attribute identifies the vendor of the ONU. It is the same as the four most significant
+//			bytes of the ONU serial number as specified in the respective transmission convergence (TC)
+//			layer specification. (R) (mandatory) (4-bytes)
 //
 //		Version
-//			Version:	This attribute identifies the version of the ONU as defined by the vendor. The
-//			character value 0 indicates that version information is not available or applicable. (R)
-//			(mandatory) (14-bytes)
+//			This attribute identifies the version of the ONU as defined by the vendor. The character value 0
+//			indicates that version information is not available or applicable. (R) (mandatory) (14-bytes)
 //
 //		Serial Number
-//			Serial number: The serial number is unique for each ONU. It is defined in the respective TC
-//			layer specification and contains the vendor ID and version number. The first four bytes are an
-//			ASCII-encoded four-letter vendor ID. The second four bytes are a binary encoded serial number,
-//			under the control of the ONU vendor. (R) (mandatory) (8-bytes)
+//			The serial number is unique for each ONU. It is defined in the respective TC layer specification
+//			and contains the vendor ID and version number. The first four bytes are an ASCII-encoded four-
+//			letter vendor ID. The second four bytes are a binary encoded serial number, under the control of
+//			the ONU vendor. (R) (mandatory) (8-bytes)
 //
 //		Traffic Management Option
+//			This attribute identifies the upstream traffic management function implemented in the ONU. There
+//			are three options:
+//
+//			0	Priority controlled and flexibly scheduled upstream traffic. The traffic scheduler and
+//			priority queue mechanism are used for upstream traffic.
+//
+//			1	Rate controlled upstream traffic. The maximum upstream traffic of each individual connection
+//			is guaranteed by shaping.
+//
+//			2	Priority and rate controlled. The traffic scheduler and priority queue mechanism are used for
+//			upstream traffic. The maximum upstream traffic of each individual connection is guaranteed by
+//			shaping.
+//
+//			For a further explanation, see Appendix II.
+//
+//			Downstream priority queues are managed via the GEM port network CTP ME.
+//
 //			Upon ME instantiation, the ONU sets this attribute to the value that describes its
 //			implementation. The OLT must adapt its model to conform to the ONU's selection. (R) (mandatory)
 //			(1-byte)
 //
 //		Deprecated
-//			Deprecated:	This attribute is not used. If it is present, it should be set to 0. (R) (optional)
-//			(1-byte)
+//			This attribute is not used. If it is present, it should be set to 0. (R) (optional) (1-byte)
 //
 //		Battery Backup
-//			Battery backup: This Boolean attribute controls whether the ONU performs backup battery
-//			monitoring (assuming it is capable of doing so). False disables battery alarm monitoring; true
-//			enables battery alarm monitoring. (R,-W) (mandatory) (1-byte)
+//			This Boolean attribute controls whether the ONU performs backup battery monitoring (assuming it
+//			is capable of doing so). False disables battery alarm monitoring; true enables battery alarm
+//			monitoring. (R,-W) (mandatory) (1-byte)
 //
 //		Administrative State
-//			Administrative state: This attribute locks (1) and unlocks (0) the functions performed by the
-//			ONU as an entirety. Administrative state is further described in clause A.1.6. (R,-W)
-//			(mandatory) (1-byte)
+//			This attribute locks (1) and unlocks (0) the functions performed by the ONU as an entirety.
+//			Administrative state is further described in clause A.1.6. (R,-W) (mandatory) (1-byte)
 //
 //		Operational State
-//			Operational state: This attribute reports whether the ME is currently capable of performing its
-//			function. Valid values are enabled (0) and disabled (1). (R) (optional) (1-byte)
+//			This attribute reports whether the ME is currently capable of performing its function. Valid
+//			values are enabled (0) and disabled (1). (R) (optional) (1-byte)
 //
 //		Onu Survival Time
-//			ONU survival time: This attribute indicates the minimum guaranteed time in milliseconds between
-//			the loss of external power and the silence of the ONU. This does not include survival time
-//			attributable to a backup battery. The value zero implies that the actual time is not known. (R)
-//			(optional) (1-byte)
+//			This attribute indicates the minimum guaranteed time in milliseconds between the loss of
+//			external power and the silence of the ONU. This does not include survival time attributable to a
+//			backup battery. The value zero implies that the actual time is not known. (R) (optional)
+//			(1-byte)
 //
 //		Logical Onu Id
-//			Logical ONU ID: This attribute provides a way for the ONU to identify itself. It is a text
-//			string, null terminated if it is shorter than 24 bytes, with a null default value. The mechanism
-//			for creation or modification of this information is beyond the scope of this Recommendation, but
-//			might include, for example, a web page displayed to a user. (R) (optional) (24 bytes)
+//			This attribute provides a way for the ONU to identify itself. It is a text string, null
+//			terminated if it is shorter than 24 bytes, with a null default value. The mechanism for creation
+//			or modification of this information is beyond the scope of this Recommendation, but might
+//			include, for example, a web page displayed to a user. (R) (optional) (24 bytes)
 //
 //		Logical Password
-//			Logical password: This attribute provides a way for the ONU to submit authentication
-//			credentials. It is a text string, null terminated if it is shorter than 12 bytes, with a null
-//			default value. The mechanism for creation or modification of this information is beyond the
-//			scope of this Recommendation. (R) (optional) (12-bytes)
+//			This attribute provides a way for the ONU to submit authentication credentials. It is a text
+//			string, null terminated if it is shorter than 12 bytes, with a null default value. The mechanism
+//			for creation or modification of this information is beyond the scope of this Recommendation. (R)
+//			(optional) (12-bytes)
 //
 //		Credentials Status
+//			This attribute permits the OLT to signal to the ONU whether its credentials are valid or not.
+//			The behaviour of the ONU is not specified, but might, for example, include displaying an error
+//			screen to the user. (R, W) (optional) (1-byte)
+//
+//			Values include:
+//
+//			0	Initial state, status indeterminate
+//
+//			1	Successful authentication
+//
+//			2	Logical ONU ID (LOID) error
+//
+//			3	Password error
+//
+//			4	Duplicate LOID
+//
 //			Other values are reserved.
 //
 //		Extended Tc_Layer Options
+//			Extended TC-layer options: This attribute is meaningful in ITU-T G.984 systems only. It is a bit
+//			map that defines whether the ONU supports (1) or does not support (0) various optional TC-layer
+//			capabilities of [ITU-T G.984.3]. Bits are assigned as follows.
+//
+//			Bit	Meaning
+//
+//			1 (LSB)	Annex C  of [ITU-T G.984.3], PON-ID maintenance.
+//
+//			2	Annex D of [ITU-T G.984.3], PLOAM channel enhancements: swift_POPUP and Ranging_adjustment
+//			messages.
+//
+//			3..16	Reserved
+//
 //			(R) (optional) (2-bytes)
 //
 type OnuG struct {
diff --git a/generated/onu2-g.go b/generated/onu2-g.go
index d9643e9..6ee350e 100644
--- a/generated/onu2-g.go
+++ b/generated/onu2-g.go
@@ -27,11 +27,11 @@
 
 // Onu2GClassID is the 16-bit ID for the OMCI
 // Managed entity ONU2-G
-const Onu2GClassID ClassID = ClassID(257)
+const Onu2GClassID = ClassID(257) // 0x0101
 
 var onu2gBME *ManagedEntityDefinition
 
-// Onu2G (class ID #257)
+// Onu2G (Class ID: #257 / 0x0101)
 //	This ME contains additional attributes associated with a PON ONU. The ONU automatically creates
 //	an instance of this ME. Its attributes are populated according to data within the ONU itself.
 //
@@ -42,46 +42,118 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. There is only
-//			one instance, number 0. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. There is only one instance, number
+//			0. (R) (mandatory) (2-bytes)
 //
 //		Equipment Id
-//			Equipment ID: This attribute may be used to identify the specific type of ONU. In some
-//			environments, this attribute may include the common language equipment identification (CLEI)
-//			code. (R) (optional) (20-bytes)
+//			This attribute may be used to identify the specific type of ONU. In some environments, this
+//			attribute may include the common language equipment identification (CLEI) code. (R) (optional)
+//			(20-bytes)
 //
 //		Optical Network Unit Management And Control Channel Omcc Version
+//			0xA3	ITU-T G.988 (2012). Baseline message set only
+//
+//			0xB0	ITU-T G.988 (2010). Baseline and extended message set
+//
+//			0xB1	ITU-T G.988 Amd.1 (2011). Baseline and extended message set
+//
+//			0xB2	ITU-T G.988 Amd.2 (2012). Baseline and extended message set
+//
+//			0xB3	ITU-T G.988 (2012). Baseline and extended message set
+//
+//			0xB4	ITU-T G.988 Amd1 (2014) Baseline and extended message set
+//
+//			0xB5	Do not use
+//
 //			(R) (mandatory) (1-byte)
 //
+//			Optical network unit management and control channel (OMCC) version: This attribute identifies
+//			the version of the OMCC protocol being used by the ONU. This allows the OLT to manage a network
+//			with ONUs that support different OMCC versions. Release levels of [ITUT G.984.4] are supported
+//			with code points of the form 0x8y and 0x9y, where y is a hexadecimal digit in the range 0..F.
+//			Support for continuing revisions of this Recommendation is defined in the 0xAy and OxBy range.
+//
+//			NOTE 1 - The complete list of managed entities supported by an ONU cannot be derived from the
+//			OMCC version attribute. Refer to other ITUT-G.988 OMCI mechanisms for deriving this information
+//			(clause I.1.1.1 which describes the use of clauses 9.12.9 Managed entity and 9.12.10 Attribute
+//			ME for retrieval of ITU-T G.988 supported ME, and clause I.1.2 for discovering the ONU hardware
+//			and service configuration of the ONU through MIB uploads.)
+//
+//			NOTE 2 -  0xBz values greater than B5 are reserved to report new ITUT-G.988 Annex A message
+//			versions (relative to ITU-T G.988 (2014) Amd1).
+//
+//			0x80	ITU-T G.984.4 (06/04)
+//
+//			NOTE - For historical reasons, this code point may also appear in ONUs that support later
+//			versions of [ITU-T G.984.4].
+//
+//			0x81	ITU-T G.984.4 2004 Amd.1 (06/05)
+//
+//			0x82	ITU-T G.984.4 2004 Amd.2 (03/06)
+//
+//			0x83	ITU-T G.984.4 2004 Amd.3 (12/06)
+//
+//			0x84	ITU-T G.984.4 2008 (02/08)
+//
+//			0x85	ITU-T G.984.4 2008 Amd.1 (06/09)
+//
+//			0x86	ITU-T G.984.4 2008 Amd.2 (2009). Baseline message set only, without the extended message
+//			set option
+//
+//			0x96	ITU-T G.984.4 2008 Amd.2 (2009). Extended message set option, in addition to the baseline
+//			message set.
+//
+//			0xA0	ITU-T G.988 (2010). Baseline message set only, without the extended message set option
+//
+//			0xA1	ITU-T G.988 Amd.1 (2011). Baseline message set only
+//
+//			0xA2	ITU-T G.988 Amd.2 (2012). Baseline message set only
+//
 //		Vendor Product Code
-//			Vendor product code: This attribute contains a vendor-specific product code for the ONU. (R)
-//			(optional) (2-bytes)
+//			This attribute contains a vendor-specific product code for the ONU. (R) (optional) (2-bytes)
 //
 //		Security Capability
+//			This attribute advertises the security capabilities of the ONU. The following code points are
+//			defined:
+//
+//			0	Reserved
+//
+//			1	Advanced encryption standard-128 (AES-128) payload encryption supported
+//
+//			2..255	Reserved
+//
 //			(R) (mandatory) (1-byte)
 //
 //		Security Mode
+//			This attribute specifies the current security mode of the ONU. All secure GEM ports in an ONU
+//			must use the same security mode at any given time. The following code points are defined:
+//
+//			0	Reserved
+//
+//			1	AES-128 algorithm
+//
+//			2..255	Reserved
+//
 //			Upon ME instantiation, the ONU sets this attribute to 1, AES-128. Attribute value 1 does not
 //			imply that any channels are encrypted; that process is negotiated at the PLOAM layer. It only
 //			signifies that the advanced encryption standard (AES) with 128-bit keys is the security mode to
 //			be used on any channels that the OLT may choose to encrypt. (R,-W) (mandatory) (1-byte)
 //
 //		Total Priority Queue Number
-//			Total priority queue number: This attribute reports the total number of upstream priority queues
-//			that are not associated with a circuit pack, but with the ONU in its entirety. Upon ME
-//			instantiation, the ONU sets this attribute to the value that represents its capabilities. (R)
-//			(mandatory) (2-bytes)
+//			This attribute reports the total number of upstream priority queues that are not associated with
+//			a circuit pack, but with the ONU in its entirety. Upon ME instantiation, the ONU sets this
+//			attribute to the value that represents its capabilities. (R) (mandatory) (2-bytes)
 //
 //		Total Traffic Scheduler Number
-//			Total traffic scheduler number: This attribute reports the total number of traffic schedulers
-//			that are not associated with a circuit pack, but with the ONU in its entirety. The ONU supports
-//			null function, strict priority scheduling and weighted round robin (WRR) from the priority
-//			control and guarantee of minimum rate control points of view, respectively. If the ONU has no
-//			global traffic schedulers, this attribute is 0. (R) (mandatory) (1-byte)
+//			This attribute reports the total number of traffic schedulers that are not associated with a
+//			circuit pack, but with the ONU in its entirety. The ONU supports null function, strict priority
+//			scheduling and weighted round robin (WRR) from the priority control and guarantee of minimum
+//			rate control points of view, respectively. If the ONU has no global traffic schedulers, this
+//			attribute is 0. (R) (mandatory) (1-byte)
 //
 //		Deprecated
-//			Deprecated:	This attribute should always be set to 1 by the ONU and ignored by the OLT. (R)
-//			(mandatory) (1-byte)
+//			This attribute should always be set to 1 by the ONU and ignored by the OLT. (R) (mandatory)
+//			(1-byte)
 //
 //		Total Gem Port_Id Number
 //			Total GEM port-ID number: This attribute reports the total number of GEM port-IDs supported by
@@ -90,22 +162,52 @@
 //			(optional) (2-bytes)
 //
 //		Sysuptime
-//			SysUpTime:	This attribute counts 10 ms intervals since the ONU was last initialized. It rolls
-//			over to 0 when full (see [IETF RFC 1213]). (R) (optional) (4-bytes)
+//			This attribute counts 10 ms intervals since the ONU was last initialized. It rolls over to 0
+//			when full (see [IETF RFC 1213]). (R) (optional) (4-bytes)
 //
 //		Connectivity Capability
+//			This attribute indicates the Ethernet connectivity models that the ONU can support. The value 0
+//			indicates that the capability is not supported; 1 signifies support. The following code points
+//			are defined.
+//
+//			NOTE 1 - It is not implied that an ONU may not support other connectivity models.
+//
 //			(R) (optional) (2 bytes)
 //
 //		Current Connectivity Mode
 //			(R, W) (optional) (1 byte)
 //
+//			This attribute specifies the Ethernet connectivity model that the OLT wishes to use. The
+//			following code points are defined.
+//
+//			NOTE 2 - It is not implied that an ONU supports a given connectivity model only when that model
+//			is explicitly selected by this attribute. The ONU is free to support additional models at any
+//			and all times.
+//
 //		Quality Of Service Qos Configuration Flexibility
+//			Quality of service (QoS) configuration flexibility: This attribute reports whether various MEs
+//			in the ONU are fixed by the ONU's architecture or whether they are configurable. For backward
+//			compatibility, and if the ONU does not support this attribute, all such attributes are
+//			understood to be hard-wired. (R) (optional) (2-bytes)
+//
+//			Discussion:
+//
+//			To allow for the possibility that the OLT does not support flexible configuration, the ONU
+//			vendor must assure that the priority queues and traffic schedulers are configured in a
+//			meaningful and useful way by factory default, and that this default configuration is restored
+//			upon ONU initialization and MIB reset. The specifics of such a configuration are beyond the
+//			scope of this Recommendation.
+//
 //			The ME ID of both the T-CONT and traffic scheduler contains a slot number. Even when attributes
 //			in the above list are RW, it is never permitted to change the slot number in a reference. That
 //			is, configuration flexibility never extends across slots. It is also not permitted to change the
 //			directionality of an upstream queue to downstream or vice versa.
 //
 //		Priority Queue Scale Factor
+//			If this optional attribute is implemented, it specifies the scale factor of several attributes
+//			of the priority queue ME of clause-9.2.10. The default value of this attribute is 1. (R, W)
+//			(optional) (2-bytes)
+//
 //			NOTE 3 - Some legacy implementations may take the queue scale factor from the GEM block length
 //			attribute of the ANI-G ME. That option is discouraged in new implementations.
 //
diff --git a/generated/onu3-g.go b/generated/onu3-g.go
new file mode 100644
index 0000000..3e156b6
--- /dev/null
+++ b/generated/onu3-g.go
@@ -0,0 +1,163 @@
+/*
+ * 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.
+ */
+/*
+ * NOTE: This file was generated, manual edits will be overwritten!
+ *
+ * Generated by 'goCodeGenerator.py':
+ *              https://github.com/cboling/OMCI-parser/README.md
+ */
+
+package generated
+
+import "github.com/deckarep/golang-set"
+
+// Onu3GClassID is the 16-bit ID for the OMCI
+// Managed entity ONU3-G
+const Onu3GClassID = ClassID(441) // 0x01b9
+
+var onu3gBME *ManagedEntityDefinition
+
+// Onu3G (Class ID: #441 / 0x01b9)
+//	This ME contains additional attributes and alarms associated with a PON ONU. The ONU
+//	automatically creates an instance of this ME. Its attributes are populated according to data
+//	within the ONU itself.
+//
+//	Upon instantiation of this ME, the Total number of status snapshots S, the Number of valid
+//	status snapshots M, and Next status snapshot index K are populated from the non-volatile memory.
+//	If the non-volatile memory values are not available (e.g., at the initialization of an off-the-
+//	shelf ONU), the Total number of status snapshots attribute is set to the maximum size of the
+//	status snapshot record table the ONU can maintain, which is a static capability parameter, while
+//	both the Number of valid status snapshots and the Next status snapshot index attributes are set
+//	to zero.
+//
+//	The Status snapshot record table is implemented as a circular buffer containing up to S records
+//	of size N. The size and format of the snapshot record are vendor-specific. Each time the ONU
+//	takes and stores a status snapshot, it increments the Number of valid status snapshots M,
+//	saturating at S, and increments Next status snapshot index K in modulo S:
+//
+//	K := (K-+ 1)mod S.
+//
+//	By writing into the Snap action attribute, the OLT instructs the ONU to immediately take a
+//	status snapshot and to store it in the Status snapshot table. By writing into Reset action
+//	attribute, the OLT instructs the ONU to erase the Status snapshot record table. The OLT uses the
+//	AVC indication of the Next status snapshot index and Number of valid status snapshots attributes
+//	to confirm that its instructions have been executed by the ONU. If the OLT has issued no Snap
+//	action instructions, a change in the value of Next status snapshot index attributes between two
+//	consecutive reads indicates that a condition has arisen that has caused the ONU to record a
+//	status snapshot.
+//
+//	Two table attributes, the Status snapshot record table, and the Most recent status snapshot,
+//	provide the OLT access to the status snapshot records. The former allows the entire Status
+//	snapshot record table to be retrieved, the latter provides quick access to the latest snapshot
+//	record.
+//
+//	By performing the Get operation on the Most recent status snapshot, the OLT can obtain the
+//	vendor-specific size of an individual snapshot record. The OLT is expected to pass the status
+//	snapshot records transparently, without parsing or interpreting them.
+//
+//	Relationships
+//		This ME is associated with the ONU-G ME.
+//
+//	Attributes
+//		Managed Entity Id
+//			This attribute uniquely identifies each instance of this ME. There is only one instance, number
+//			0. (R) (mandatory) (2-bytes)
+//
+//		Flash Memory Performance Value
+//			A number in the range from 0 to 100 that characterizes the condition of the flash memory, with 0
+//			representing factory fresh device, 100 representing end of life. This attribute is vendor-
+//			specific and should be calculated at the discretion of the vendor. (R) (optional) (1-byte)
+//
+//		Latest Restart Reason
+//			The following code points are defined:
+//
+//		Total Number Of Status Snapshots
+//			The maximum size S of the status snapshot record table. (R) (mandatory) (2-bytes)
+//
+//		Number Of Valid Status Snapshots
+//			The number M of valid status snapshot records. (R) (mandatory) (2-bytes)
+//
+//		Next Status Snapshot Index
+//			This attribute identifies the index (ranging from 0 to S-- 1) of the next snapshot record to be
+//			taken in the snapshot record table. (R,) (mandatory) (2-bytes)
+//
+//		Status Snapshot Record Table
+//			The table of M status snapshot records. The size N and format of the snapshot record is vendor
+//			dependent. (R) (mandatory) (MxN-bytes)
+//
+//		Snap Action
+//			Once the OLT writes this attribute, the ONU takes and records an urgent snapshot without
+//			shutting down the transceiver. (W) (mandatory) (1-byte)
+//
+//		Most Recent Status Snapshot
+//			This attribute provides access to the most recently taken status snapshot record. (R)
+//			(mandatory) (N-bytes)
+//
+//		Reset Action
+//			Once the OLT writes this attribute, the ONU sets the Number of valid status snapshots and Next
+//			status snapshot index attributes to zero. (W) (mandatory) (1-byte)
+//
+//		Enhanced Mode
+//			The Boolean value true specifies the Enhanced received frame classification and processing table
+//			is supported by the Extended VLAN tagging operation configuration ME. The value false indicates
+//			the Enhanced received frame classification and processing table is not supported. (R) (optional)
+//			(1-byte)
+//
+type Onu3G struct {
+	ManagedEntityDefinition
+	Attributes AttributeValueMap
+}
+
+func init() {
+	onu3gBME = &ManagedEntityDefinition{
+		Name:    "Onu3G",
+		ClassID: 441,
+		MessageTypes: mapset.NewSetWith(
+			Get,
+		),
+		AllowedAttributeMask: 0xffc0,
+		AttributeDefinitions: AttributeDefinitionMap{
+			0:  Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read), false, false, false, 0),
+			1:  ByteField("FlashMemoryPerformanceValue", UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read), true, true, false, 1),
+			2:  ByteField("LatestRestartReason", UnsignedIntegerAttributeType, 0x4000, 0, mapset.NewSetWith(Read), false, false, false, 2),
+			3:  Uint16Field("TotalNumberOfStatusSnapshots", UnsignedIntegerAttributeType, 0x2000, 0, mapset.NewSetWith(Read), true, false, false, 3),
+			4:  Uint16Field("NumberOfValidStatusSnapshots", UnsignedIntegerAttributeType, 0x1000, 0, mapset.NewSetWith(Read), false, false, false, 4),
+			5:  Uint16Field("NextStatusSnapshotIndex", UnsignedIntegerAttributeType, 0x0800, 0, mapset.NewSetWith(Read), false, false, false, 5),
+			6:  MultiByteField("StatusSnapshotRecordTable", OctetsAttributeType, 0x0400, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read), false, false, false, 6),
+			7:  ByteField("SnapAction", UnsignedIntegerAttributeType, 0x0200, 0, mapset.NewSetWith(Write), false, false, false, 7),
+			8:  MultiByteField("MostRecentStatusSnapshot", OctetsAttributeType, 0x0100, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read), false, false, false, 8),
+			9:  ByteField("ResetAction", UnsignedIntegerAttributeType, 0x0080, 0, mapset.NewSetWith(Write), false, false, false, 9),
+			10: ByteField("EnhancedMode", UnsignedIntegerAttributeType, 0x0040, 0, mapset.NewSetWith(Read), false, true, false, 10),
+		},
+		Access:  CreatedByOnu,
+		Support: UnknownSupport,
+		Alarms: AlarmMap{
+			0: "Flash memory performance yellow",
+			1: "Flash memory performance red",
+			2: "Loss of redundant power supply",
+			3: "Loss of redundant power feed",
+			4: "Ground Fault",
+		},
+	}
+}
+
+// NewOnu3G (class ID 441) creates the basic
+// Managed Entity definition that is used to validate an ME of this type that
+// is received from or transmitted to the OMCC.
+func NewOnu3G(params ...ParamData) (*ManagedEntity, OmciErrors) {
+	return NewManagedEntity(*onu3gBME, params...)
+}
diff --git a/generated/onudata.go b/generated/onudata.go
index 8cb4a8f..4e22678 100644
--- a/generated/onudata.go
+++ b/generated/onudata.go
@@ -27,11 +27,11 @@
 
 // OnuDataClassID is the 16-bit ID for the OMCI
 // Managed entity ONU data
-const OnuDataClassID ClassID = ClassID(2)
+const OnuDataClassID = ClassID(2) // 0x0002
 
 var onudataBME *ManagedEntityDefinition
 
-// OnuData (class ID #2)
+// OnuData (Class ID: #2 / 0x0002)
 //	This ME models the MIB itself. Clause I.1.3 explains the use of this ME with respect to MIB
 //	synchronization.
 //
@@ -43,15 +43,15 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. There is only
-//			one instance, number 0. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. There is only one instance, number
+//			0. (R) (mandatory) (2-bytes)
 //
 //		Mib Data Sync
-//			MIB data sync: This attribute is used to check the alignment of the MIB of the ONU with the
-//			corresponding MIB in the OLT. MIB data sync relies on this attribute, which is a sequence number
-//			that can be checked by the OLT to see if the MIB snapshots for the OLT and ONU match. Refer to
-//			clause I.1.2.1 for a detailed description of this attribute. Upon ME instantiation, the ONU sets
-//			this attribute to 0. (R,-W) (mandatory) (1-byte)
+//			This attribute is used to check the alignment of the MIB of the ONU with the corresponding MIB
+//			in the OLT. MIB data sync relies on this attribute, which is a sequence number that can be
+//			checked by the OLT to see if the MIB snapshots for the OLT and ONU match. Refer to clause
+//			I.1.2.1 for a detailed description of this attribute. Upon ME instantiation, the ONU sets this
+//			attribute to 0. (R,-W) (mandatory) (1-byte)
 //
 type OnuData struct {
 	ManagedEntityDefinition
diff --git a/generated/onudynamicpowermanagementcontrol.go b/generated/onudynamicpowermanagementcontrol.go
index da0180f..ebb2f39 100644
--- a/generated/onudynamicpowermanagementcontrol.go
+++ b/generated/onudynamicpowermanagementcontrol.go
@@ -27,11 +27,11 @@
 
 // OnuDynamicPowerManagementControlClassID is the 16-bit ID for the OMCI
 // Managed entity ONU dynamic power management control
-const OnuDynamicPowerManagementControlClassID ClassID = ClassID(336)
+const OnuDynamicPowerManagementControlClassID = ClassID(336) // 0x0150
 
 var onudynamicpowermanagementcontrolBME *ManagedEntityDefinition
 
-// OnuDynamicPowerManagementControl (class ID #336)
+// OnuDynamicPowerManagementControl (Class ID: #336 / 0x0150)
 //	This ME models the ONU's ability to enter power conservation modes in cooperation with the OLT
 //	in an ITU-T G.987 system. [ITUT G.987.3] originally specified two alternative modes, doze and
 //	cyclic sleep. The subsequent revision of [ITUT G.987.3] simplified the specification providing a
@@ -44,38 +44,56 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. There is only
-//			one instance, number 0. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. There is only one instance, number
+//			0. (R) (mandatory) (2-bytes)
 //
 //		Power Reduction Management Capability
+//			This attribute declares the ONU's support for managed power conservation modes, as defined in
+//			[ITUT G.987.3]. It is a bit map in which the bit value 0 indicates no support for the specified
+//			mode, while the bit value 1 indicates that the ONU does support the specified mode. (R)
+//			(mandatory) (1-byte)
+//
+//			Codepoints are assigned as follows:
+//
+//			Value	Meaning
+//
+//			0	No support for power reduction
+//
+//			1	Doze mode supported
+//
+//			2	Cyclic sleep mode supported
+//
+//			3	Both doze and cyclic sleep modes supported
+//
+//			4	Watchful sleep mode supported
+//
 //			5..255	Reserved
 //
 //		Power Reduction Management Mode
-//			Power reduction management mode: This attribute enables one or more of the ONU's managed power
-//			conservation modes. It is a bit map in which the bit value 0 disables the mode, while the value
-//			1 enables the mode. Bit assignments are the same as those of the power reduction management
-//			capability attribute. The default value of each bit is 0. (R,-W) (mandatory) (1-byte)
+//			This attribute enables one or more of the ONU's managed power conservation modes. It is a bit
+//			map in which the bit value 0 disables the mode, while the value 1 enables the mode. Bit
+//			assignments are the same as those of the power reduction management capability attribute. The
+//			default value of each bit is 0. (R,-W) (mandatory) (1-byte)
 //
 //		Itransinit
-//			Itransinit:	This attribute is the ONU vendor's statement of the complete transceiver
-//			initialization time: the worst-case time required for the ONU to regain full functionality when
-//			leaving the asleep state in cyclic sleep mode or low-power state in watchful sleep mode (i.e.,
-//			turning on both the receiver and the transmitter and acquiring synchronization to the downstream
-//			flow), measured in units of 125-us frames. The value zero indicates that the sleeping ONU can
-//			respond to a bandwidth grant without delay. (R) (mandatory) (2-bytes)
+//			This attribute is the ONU vendor's statement of the complete transceiver initialization time:
+//			the worst-case time required for the ONU to regain full functionality when leaving the asleep
+//			state in cyclic sleep mode or low-power state in watchful sleep mode (i.e., turning on both the
+//			receiver and the transmitter and acquiring synchronization to the downstream flow), measured in
+//			units of 125-us frames. The value zero indicates that the sleeping ONU can respond to a
+//			bandwidth grant without delay. (R) (mandatory) (2-bytes)
 //
 //		Itxinit
-//			Itxinit:	This attribute is the ONU vendor's statement of the transmitter initialization time:
-//			the time required for the ONU to regain full functionality when leaving the listen state (i.e.,
-//			turning on the transmitter), measured in units of 125-us frames. The value zero indicates that
-//			the dozing ONU can respond to a bandwidth grant without delay. If watchful sleep is enabled, the
-//			ONU ignores this attribute. (R) (mandatory) (2 bytes)
+//			This attribute is the ONU vendor's statement of the transmitter initialization time: the time
+//			required for the ONU to regain full functionality when leaving the listen state (i.e., turning
+//			on the transmitter), measured in units of 125-us frames. The value zero indicates that the
+//			dozing ONU can respond to a bandwidth grant without delay. If watchful sleep is enabled, the ONU
+//			ignores this attribute. (R) (mandatory) (2 bytes)
 //
 //		Maximum Sleep Interval
-//			Maximum sleep interval: The Isleep/Ilowpower attribute specifies the maximum time the ONU spends
-//			in its asleep, listen, or low-power states, as a count of 125-us frames. Local or remote events
-//			may truncate the ONU's sojourn in these states. The default value of this attribute is 0. (R,-W)
-//			(mandatory) (4-bytes)
+//			The Isleep/Ilowpower attribute specifies the maximum time the ONU spends in its asleep, listen,
+//			or low-power states, as a count of 125-us frames. Local or remote events may truncate the ONU's
+//			sojourn in these states. The default value of this attribute is 0. (R,-W) (mandatory) (4-bytes)
 //
 //		Maximum Receiver_Off Interval
 //			Maximum receiver-off interval: The Irxoff attribute specifies the maximum time the OLT can
@@ -84,30 +102,50 @@
 //			(R,-W) (mandatory) (4-bytes)
 //
 //		Minimum Aware Interval
-//			Minimum aware interval: The Iaware attribute specifies the time the ONU spends in its aware
-//			state, as a count of 125-us frames, before it re-enters asleep or listen states. Local or remote
-//			events may independently cause the ONU to enter an active state rather than returning to a sleep
-//			state. The default value of this attribute is 0. (R,-W) (mandatory) (4-bytes)
+//			The Iaware attribute specifies the time the ONU spends in its aware state, as a count of 125-us
+//			frames, before it re-enters asleep or listen states. Local or remote events may independently
+//			cause the ONU to enter an active state rather than returning to a sleep state. The default value
+//			of this attribute is 0. (R,-W) (mandatory) (4-bytes)
 //
 //		Minimum Active Held Interval
-//			Minimum active held interval: The Ihold attribute specifies the minimum time during which the
-//			ONU remains in the active held state, as a count of 125-us frames. Its initial value is zero.
-//			(R, W) (mandatory) (2-bytes)
+//			The Ihold attribute specifies the minimum time during which the ONU remains in the active held
+//			state, as a count of 125-us frames. Its initial value is zero. (R, W) (mandatory) (2-bytes)
 //
 //		Maximum Sleep Interval Extension
+//			Maximum sleep interval for doze mode specifies the maximum time the ONU spends in its listen
+//			state, as a count of 125-us frames. Local or remote events may truncate the ONU's sojourn in
+//			these states. The default value is 0.
+//
+//			Maximum sleep interval for cyclic sleep mode specifies the maximum time the ONU spends in its
+//			asleep state, as a count of 125-us frames. Local or remote events may truncate the ONU's sojourn
+//			in these states. The default value is 0. If watchful sleep is enabled, the ONU ignores this
+//			attribute.
+//
 //			(R,-W) (optional) (8-bytes)
 //
+//			This attribute designates maximum sleep interval values for doze mode and cyclic sleep mode
+//			separately. When it supports this attribute, the ONU ignores the value of the maximum sleep
+//			interval attribute.
+//
+//			Maximum sleep interval for doze mode	4-bytes
+//
+//			Maximum sleep interval for cyclic sleep mode	4-bytes
+//
 //		Ethernet Passive Optical Network Epon Capability Extension
-//			-	Configurations: ackEnable configuration = enable, Sleep indication configuration = disable,
-//			Early wake-up configuration = enable
+//			Ethernet passive optical network (EPON) capability extension: This attribute declares EPON-
+//			specific capabilities for the dynamic power management control.
+//
+//			Bits are assigned as follows.
 //
 //		Epon Setup Extension
-//			(R,-W) (optional) (1-byte)
+//			The bits are assigned as follows.
+//
+//			This attribute specifies EPON specific configurations for the dynamic power management control.
 //
 //		Missing Consecutive Bursts Threshold
-//			Missing consecutive bursts threshold: The Clobi attribute specifies the maximum number of
-//			missing consecutive scheduled bursts from the ONU that the OLT is willing to tolerate without
-//			raising an alarm. The value of this attribute defaults to 4. (R,-W) (mandatory) (4-bytes)
+//			The Clobi attribute specifies the maximum number of missing consecutive scheduled bursts from
+//			the ONU that the OLT is willing to tolerate without raising an alarm. The value of this
+//			attribute defaults to 4. (R,-W) (mandatory) (4-bytes)
 //
 type OnuDynamicPowerManagementControl struct {
 	ManagedEntityDefinition
diff --git a/generated/onumanufacturingdata.go b/generated/onumanufacturingdata.go
new file mode 100644
index 0000000..8e01750
--- /dev/null
+++ b/generated/onumanufacturingdata.go
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+/*
+ * NOTE: This file was generated, manual edits will be overwritten!
+ *
+ * Generated by 'goCodeGenerator.py':
+ *              https://github.com/cboling/OMCI-parser/README.md
+ */
+
+package generated
+
+import "github.com/deckarep/golang-set"
+
+// OnuManufacturingDataClassID is the 16-bit ID for the OMCI
+// Managed entity ONU manufacturing data
+const OnuManufacturingDataClassID = ClassID(456) // 0x01c8
+
+var onumanufacturingdataBME *ManagedEntityDefinition
+
+// OnuManufacturingData (Class ID: #456 / 0x01c8)
+//	This ME contains additional manufacturing attributes associated with a PON ONU. The
+//	manufacturing data is expected to match the content of an ONU label. The ONU automatically
+//	creates an instance of this ME. Its attributes are populated according to data within the ONU
+//	itself.
+//
+//	Relationships
+//		This ME is paired with the ONU-G entity.
+//
+//	Attributes
+//		Managed Entity Id
+//			This attribute uniquely identifies each instance of this ME. There is only one instance, number
+//			0. (R) (mandatory) (2-bytes)
+//
+//		Manufacturer Name
+//			This attribute contains the manufacturer name of this physical ONU. The preferred value is the
+//			manufacturer name string printed on the ONU itself (if present). (R) (optional) (25 bytes)
+//
+//		Serial Number Part 1, Serial Number Part 2
+//			These two attributes may be regarded as an ASCII string of up to 32 bytes whose length is a left
+//			justified manufacturer's serial number for this physical ONU. The preferred value is the
+//			manufacturer serial number string printed on the ONU itself (if present). (R) (optional)
+//			(25-bytes*2 attributes)
+//
+//		Model Name
+//			This attribute contains the vendor specific model name identifier string. The preferred value is
+//			the customer-visible part number which may be printed on the component itself. (R) (optional)
+//			(25 bytes)
+//
+//		Manufacturing Date
+//			This attribute contains the date of manufacturer of this physical ONU. The preferred value is
+//			the date of the manufacturer printed on the ONU itself (if present). (R) (optional) (25 bytes)
+//
+//		Hardware_Revision
+//			Hardware-revision: This attribute contains the hardware revision of this physical ONU. The
+//			preferred value is the hardware revision printed on the ONU itself (if present). (R) (optional)
+//			(25 bytes)
+//
+//		Firmware_Revision
+//			Firmware-revision: This attribute contains the vendor specific firmware revision of this
+//			physical ONU. (R) (optional) (25 bytes)
+//
+type OnuManufacturingData struct {
+	ManagedEntityDefinition
+	Attributes AttributeValueMap
+}
+
+func init() {
+	onumanufacturingdataBME = &ManagedEntityDefinition{
+		Name:    "OnuManufacturingData",
+		ClassID: 456,
+		MessageTypes: mapset.NewSetWith(
+			Get,
+		),
+		AllowedAttributeMask: 0xfc00,
+		AttributeDefinitions: AttributeDefinitionMap{
+			0: Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read), false, false, false, 0),
+			1: MultiByteField("ManufacturerName", OctetsAttributeType, 0x8000, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read), false, true, false, 1),
+			2: MultiByteField("SerialNumberPart1,SerialNumberPart2", OctetsAttributeType, 0x4000, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read), false, true, false, 2),
+			3: MultiByteField("ModelName", OctetsAttributeType, 0x2000, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read), false, true, false, 3),
+			4: MultiByteField("ManufacturingDate", OctetsAttributeType, 0x1000, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read), false, true, false, 4),
+			5: MultiByteField("HardwareRevision", OctetsAttributeType, 0x0800, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read), false, true, false, 5),
+			6: MultiByteField("FirmwareRevision", OctetsAttributeType, 0x0400, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Read), false, true, false, 6),
+		},
+		Access:  CreatedByOnu,
+		Support: UnknownSupport,
+	}
+}
+
+// NewOnuManufacturingData (class ID 456) creates the basic
+// Managed Entity definition that is used to validate an ME of this type that
+// is received from or transmitted to the OMCC.
+func NewOnuManufacturingData(params ...ParamData) (*ManagedEntity, OmciErrors) {
+	return NewManagedEntity(*onumanufacturingdataBME, params...)
+}
diff --git a/generated/onupowershedding.go b/generated/onupowershedding.go
index c1931b6..e791ace 100644
--- a/generated/onupowershedding.go
+++ b/generated/onupowershedding.go
@@ -27,11 +27,11 @@
 
 // OnuPowerSheddingClassID is the 16-bit ID for the OMCI
 // Managed entity ONU power shedding
-const OnuPowerSheddingClassID ClassID = ClassID(133)
+const OnuPowerSheddingClassID = ClassID(133) // 0x0085
 
 var onupowersheddingBME *ManagedEntityDefinition
 
-// OnuPowerShedding (class ID #133)
+// OnuPowerShedding (Class ID: #133 / 0x0085)
 //	This ME models the ONU's ability to shed services when the ONU goes into battery operation mode
 //	after AC power failure. Shedding classes are defined in the following table, which may span
 //	multiple circuit pack types. This feature works in conjunction with the power shed override
@@ -53,43 +53,72 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. There is only
-//			one instance, number 0. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. There is only one instance, number
+//			0. (R) (mandatory) (2-bytes)
 //
 //		Restore Power Timer Reset Interval
-//			Restore power timer reset interval: The time delay, in seconds, before resetting the power-
-//			shedding timers after full power restoration. Upon ME instantiation, the ONU sets this attribute
-//			to 0. (R,-W) (mandatory) (2-bytes)
+//			The time delay, in seconds, before resetting the power-shedding timers after full power
+//			restoration. Upon ME instantiation, the ONU sets this attribute to 0. (R,-W) (mandatory)
+//			(2-bytes)
+//
+//			For each class of service (CoS), an interval attribute is defined below. The value 0 disables
+//			power shedding, while the value 1 enables immediate power shedding, i.e., as soon as AC power
+//			fails. Other values specify the time, in seconds, to keep the service active after AC failure
+//			before shutting them down and shedding power. Upon ME instantiation, the ONU sets each of the
+//			interval attributes to 0.
 //
 //		Data Class Shedding Interval
-//			Data class shedding interval:	(R,-W) (mandatory) (2-bytes)
+//			(R,-W) (mandatory) (2-bytes)
 //
 //		Voice Class Shedding Interval
-//			Voice class shedding interval: This attribute only pertains to voice services that terminate on
-//			the ONU and are under the management control of the OMCI. 	(R,-W) (mandatory) (2-bytes)
+//			This attribute only pertains to voice services that terminate on the ONU and are under the
+//			management control of the OMCI. 	(R,-W) (mandatory) (2-bytes)
 //
 //		Video Overlay Class Shedding Interval
-//			Video overlay class shedding interval:	(R,-W) (mandatory) (2-bytes)
+//			(R,-W) (mandatory) (2-bytes)
 //
 //		Video Return Class Shedding Interval
-//			Video return class shedding interval:	(R,-W) (mandatory) (2-bytes)
+//			(R,-W) (mandatory) (2-bytes)
 //
 //		Digital Subscriber Line Class Shedding Interval
 //			Digital subscriber line (DSL) class shedding interval:	(R,-W) (mandatory) (2-bytes)
 //
 //		Atm Class Shedding Interval
-//			ATM class shedding interval:	(R,-W) (mandatory) (2-bytes)
+//			(R,-W) (mandatory) (2-bytes)
 //
 //		Ces Class Shedding Interval
-//			CES class shedding interval:	(R,-W) (mandatory) (2-bytes)
+//			(R,-W) (mandatory) (2-bytes)
 //
 //		Frame Class Shedding Interval
-//			Frame class shedding interval:	(R,-W) (mandatory) (2-bytes)
+//			(R,-W) (mandatory) (2-bytes)
 //
 //		Sdh_Sonet Class Shedding Interval
 //			Sdh-sonet class shedding interval:	(R,-W) (mandatory) (2-bytes)
 //
 //		Shedding Status
+//			Binary indication of power-shedding status for each shedding class. If this 2 byte field is
+//			depicted 0b ABCD EFGH IJKL MNOP, its bits are assigned as follows-
+//
+//			A	Data class
+//
+//			B	Voice class
+//
+//			C	Video overlay class
+//
+//			D	Video return class
+//
+//			E	DSL class
+//
+//			F	ATM class
+//
+//			G	CES class
+//
+//			H	Frame class
+//
+//			I	Sdh-sonet class
+//
+//			J..P	Reserved and set to 0
+//
 //			The ONU sets each bit to 1 when power shedding is active, and clears it to 0 when the service is
 //			restored. (R) (optional) (2-bytes)
 //
diff --git a/generated/onuremotedebug.go b/generated/onuremotedebug.go
new file mode 100644
index 0000000..5a242ac
--- /dev/null
+++ b/generated/onuremotedebug.go
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+/*
+ * NOTE: This file was generated, manual edits will be overwritten!
+ *
+ * Generated by 'goCodeGenerator.py':
+ *              https://github.com/cboling/OMCI-parser/README.md
+ */
+
+package generated
+
+import "github.com/deckarep/golang-set"
+
+// OnuRemoteDebugClassID is the 16-bit ID for the OMCI
+// Managed entity ONU remote debug
+const OnuRemoteDebugClassID = ClassID(158) // 0x009e
+
+var onuremotedebugBME *ManagedEntityDefinition
+
+// OnuRemoteDebug (Class ID: #158 / 0x009e)
+//	This ME is used to send vendor-specific debug commands to the ONU and receive vendor-specific
+//	replies back for processing on the OLT. This allows for the remote debugging of an ONU that may
+//	not be accessible by other means. The command format may have two modes, one being text and the
+//	other free format. In text format, both the command and reply are ASCII strings, but are
+//	otherwise unconstrained. In free format, the content and format of command and reply are vendor-
+//	specific.
+//
+//	An ONU that supports remote debugging automatically creates an instance of this ME. It is not
+//	reported during an MIB upload.
+//
+//	Relationships
+//		One instance of this ME is associated with the ONU ME.
+//
+//	Attributes
+//		Managed Entity Id
+//			This attribute uniquely identifies each instance of this ME. There is only one instance, number
+//			0. (R) (mandatory) (2-bytes)
+//
+//		Command Format
+//			This attribute defines the format of the command and reply attributes. The value 0 defines ASCII
+//			string format, while 1 specifies free format. (R) (mandatory) (1-byte)
+//
+//		Command
+//			This attribute is used to send a command to the ONU. The format of the command is defined by the
+//			command format. If the format is ASCII string, the command should be null terminated unless the
+//			string is exactly 25-bytes long. The action of setting this attribute should trigger the ONU to
+//			discard any previous command reply information and execute the current debugging command. (W)
+//			(mandatory) (25-bytes)
+//
+//		Reply Table
+//			This attribute is used to pass reply information back to the OLT. Its format is defined by the
+//			command format attribute. The get, get next action sequence must be used with this attribute,
+//			since its size is unspecified. (R) (mandatory) (N bytes)
+//
+type OnuRemoteDebug struct {
+	ManagedEntityDefinition
+	Attributes AttributeValueMap
+}
+
+func init() {
+	onuremotedebugBME = &ManagedEntityDefinition{
+		Name:    "OnuRemoteDebug",
+		ClassID: 158,
+		MessageTypes: mapset.NewSetWith(
+			Get,
+			GetNext,
+			Set,
+		),
+		AllowedAttributeMask: 0xe000,
+		AttributeDefinitions: AttributeDefinitionMap{
+			0: Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read), false, false, false, 0),
+			1: ByteField("CommandFormat", UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read), false, false, false, 1),
+			2: MultiByteField("Command", OctetsAttributeType, 0x4000, 25, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), mapset.NewSetWith(Write), false, false, false, 2),
+			3: TableField("ReplyTable", TableAttributeType, 0x2000, TableInfo{nil, -1}, mapset.NewSetWith(Read), false, false, false, 3),
+		},
+		Access:  CreatedByOnu,
+		Support: UnknownSupport,
+	}
+}
+
+// NewOnuRemoteDebug (class ID 158) creates the basic
+// Managed Entity definition that is used to validate an ME of this type that
+// is received from or transmitted to the OMCC.
+func NewOnuRemoteDebug(params ...ParamData) (*ManagedEntity, OmciErrors) {
+	return NewManagedEntity(*onuremotedebugBME, params...)
+}
diff --git a/generated/onutimeconfiguration.go b/generated/onutimeconfiguration.go
new file mode 100644
index 0000000..7f25731
--- /dev/null
+++ b/generated/onutimeconfiguration.go
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+/*
+ * NOTE: This file was generated, manual edits will be overwritten!
+ *
+ * Generated by 'goCodeGenerator.py':
+ *              https://github.com/cboling/OMCI-parser/README.md
+ */
+
+package generated
+
+import "github.com/deckarep/golang-set"
+
+// OnuTimeConfigurationClassID is the 16-bit ID for the OMCI
+// Managed entity ONU time configuration
+const OnuTimeConfigurationClassID = ClassID(457) // 0x01c9
+
+var onutimeconfigurationBME *ManagedEntityDefinition
+
+// OnuTimeConfiguration (Class ID: #457 / 0x01c9)
+//	This ME provides characterization and manipulation of OLT timestamp information. An ONU that
+//	uses OLTbased time synchronization methods automatically creates an instance of this ME. There
+//	is no intention that this ME be used to establish a precise time of day reference.
+//
+//	Relationships
+//		The single instance of this ME is associated with the ONU ME.
+//
+//	Attributes
+//		Managed Entity Id
+//			This attribute uniquely identifies each instance of this ME. There is only one instance, number
+//			0. (R) (mandatory) (2 bytes)
+//
+//		Current Local Onu Time
+//			If the ONU has a real-time clock, it returns the local ONU time. This attribute returns the
+//			current ONU time. The local ONU time and synchronize time time-format is the same. (R)
+//			(mandatory) (7 bytes)
+//
+//		Time Qualification Block
+//			This attribute describes the time-qualification to be applied to the ONU RTC local time. The
+//			following fields are supported:
+//
+//			(R, W) (mandatory) (2 bytes)
+//
+type OnuTimeConfiguration struct {
+	ManagedEntityDefinition
+	Attributes AttributeValueMap
+}
+
+func init() {
+	onutimeconfigurationBME = &ManagedEntityDefinition{
+		Name:    "OnuTimeConfiguration",
+		ClassID: 457,
+		MessageTypes: mapset.NewSetWith(
+			Get,
+			Set,
+		),
+		AllowedAttributeMask: 0xc000,
+		AttributeDefinitions: AttributeDefinitionMap{
+			0: Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read), false, false, false, 0),
+			1: MultiByteField("CurrentLocalOnuTime", OctetsAttributeType, 0x8000, 7, toOctets("AAAAAAAAAA=="), mapset.NewSetWith(Read), false, false, false, 1),
+			2: Uint16Field("TimeQualificationBlock", UnsignedIntegerAttributeType, 0x4000, 0, mapset.NewSetWith(Read, Write), false, false, false, 2),
+		},
+		Access:  CreatedByOnu,
+		Support: UnknownSupport,
+	}
+}
+
+// NewOnuTimeConfiguration (class ID 457) creates the basic
+// Managed Entity definition that is used to validate an ME of this type that
+// is received from or transmitted to the OMCC.
+func NewOnuTimeConfiguration(params ...ParamData) (*ManagedEntity, OmciErrors) {
+	return NewManagedEntity(*onutimeconfigurationBME, params...)
+}
diff --git a/generated/physicalpathterminationpointcesuni.go b/generated/physicalpathterminationpointcesuni.go
index cc66a16..a863363 100644
--- a/generated/physicalpathterminationpointcesuni.go
+++ b/generated/physicalpathterminationpointcesuni.go
@@ -27,11 +27,11 @@
 
 // PhysicalPathTerminationPointCesUniClassID is the 16-bit ID for the OMCI
 // Managed entity Physical path termination point CES UNI
-const PhysicalPathTerminationPointCesUniClassID ClassID = ClassID(12)
+const PhysicalPathTerminationPointCesUniClassID = ClassID(12) // 0x000c
 
 var physicalpathterminationpointcesuniBME *ManagedEntityDefinition
 
-// PhysicalPathTerminationPointCesUni (class ID #12)
+// PhysicalPathTerminationPointCesUni (Class ID: #12 / 0x000c)
 //	This ME represents the point at a CES UNI in the ONU where the physical path terminates and
 //	physical level functions are performed.
 //
@@ -55,60 +55,157 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. This 2 byte
-//			number indicates the physical position of the UNI. The first byte is the slot ID (defined in
-//			clause 9.1.5). The second byte is the port ID, with the range 1..255. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. This 2 byte number indicates the
+//			physical position of the UNI. The first byte is the slot ID (defined in clause 9.1.5). The
+//			second byte is the port ID, with the range 1..255. (R) (mandatory) (2-bytes)
 //
 //		Expected Type
+//			1 to 254	One of the values from Table-9.1.5-1 that is compatible with a CES circuit pack
+//
 //			Upon ME instantiation, the ONU sets this attribute to 0. (R,-W) (mandatory) (1-byte)
 //
+//			The following coding is used for this attribute-
+//
+//			0	Autosense
+//
 //		Sensed Type
-//			Sensed type:	If the value of expected type is not 0, then the value of sensed type equals the
-//			value of expected type. If expected type-= 0, then the value of sensed type is one of the
-//			compatible values from Table-9.1.5-1. Upon ME instantiation, the ONU sets this attribute to 0 or
-//			to the value that reflects the physically present equipment. (R) (mandatory if the ONU supports
-//			circuit packs with configurable interface types, e.g., C1.5/2/6.3) (1-byte)
+//			If the value of expected type is not 0, then the value of sensed type equals the value of
+//			expected type. If expected type-= 0, then the value of sensed type is one of the compatible
+//			values from Table-9.1.5-1. Upon ME instantiation, the ONU sets this attribute to 0 or to the
+//			value that reflects the physically present equipment. (R) (mandatory if the ONU supports circuit
+//			packs with configurable interface types, e.g., C1.5/2/6.3) (1-byte)
 //
 //		Ces Loopback Configuration
+//			This attribute specifies and reports the loopback configuration of the physical interface.
+//
+//			0	No loopback
+//
+//			1	Payload loopback
+//
+//			2	Line loopback
+//
+//			3	Operations system-directed (OS-directed) loopback 1 (loopback from/to PON side)
+//
+//			4	OS-directed loopback 2 (loopback from/to CES UNI side)
+//
+//			5	OS-directed loopback 3 (loopback of both PON side and CES UNI side)
+//
+//			6	Manual button-directed loopback [read only (RO)]
+//
+//			7	Network-side code inband-directed loopback (RO)
+//
+//			8	SmartJack-directed loopback (RO)
+//
+//			9	Network-side code inband-directed loopback (armed; RO)
+//
+//			10	Remote-line loopback via facility data link (FDL)
+//
+//			11	Remote-line loopback via inband code
+//
+//			12	Remote-payload loopback
+//
 //			Upon ME instantiation, the ONU sets this attribute to 0. (R,-W) (mandatory) (1-byte)
 //
 //		Administrative State
-//			Administrative state: This attribute locks (1) and unlocks (0) the functions performed by this
-//			ME. Administrative state is further described in clause A.1.6. (R,-W) (mandatory) (1-byte)
+//			This attribute locks (1) and unlocks (0) the functions performed by this ME. Administrative
+//			state is further described in clause A.1.6. (R,-W) (mandatory) (1-byte)
 //
 //		Operational State
-//			Operational state: This attribute indicates whether the ME is capable of performing its
-//			function. Valid values are enabled (0) and disabled (1). (R) (optional) (1-byte)
+//			This attribute indicates whether the ME is capable of performing its function. Valid values are
+//			enabled (0) and disabled (1). (R) (optional) (1-byte)
 //
 //		Framing
+//			6	Basic framing with CRC-4: clause 2.3.3 of [ITU-T G.704]
+//
+//			7	Basic framing with TS16 multiframe
+//
+//			8	Basic framing with CRC-4 and TS16 multiframe
+//
 //			Upon ME instantiation, the ONU sets this attribute to a value that reflects the vendor's
 //			default. (R,-W) (optional) (1-byte)
 //
+//			This attribute specifies the framing structure.
+//
+//			These code points are for use with DS1 services. Code point 2 may also be used for an unframed
+//			E1 service.
+//
+//			0	Extended superframe
+//
+//			1	Superframe
+//
+//			2	Unframed
+//
+//			3	ITUT-G.704
+//
+//			NOTE - [ITUT G.704] describes both SF and ESF framing for DS1 signals. This code point is
+//			retained for backward compatibility, but its meaning is undefined.
+//
+//			4	JT-G.704
+//
+//			The following code points are for use with E1 services.
+//
+//			5	Basic framing: clause 2.3.2 of [ITU-T G.704]
+//
 //		Encoding
+//			This attribute specifies the line coding scheme. Valid values are as follows.
+//
+//			0	B8ZS
+//
+//			1	AMI
+//
+//			2	HDB3
+//
+//			3	B3ZS
+//
 //			Upon ME instantiation, the ONU sets this attribute to 0. (R,-W) (mandatory for DS1 and DS3
 //			interfaces) (1-byte)
 //
 //		Line Length
-//			Line length:	This attribute specifies the length of the twisted pair cable from a DS1 physical
-//			UNI to the DSX-1 cross-connect point or the length of coaxial cable from a DS3 physical UNI to
-//			the DSX-3 cross-connect point. Valid values are given in Table 9.8.1-1. Upon ME instantiation
-//			for a DS1 interface, the ONU assigns the value 0 for non-power feed type DS1 and the value 6 for
-//			power feed type DS1. Upon ME instantiation for a DS3 interface, the ONU sets this attribute to
-//			0x0F. (R,-W) (optional) (1-byte)
+//			This attribute specifies the length of the twisted pair cable from a DS1 physical UNI to the
+//			DSX-1 cross-connect point or the length of coaxial cable from a DS3 physical UNI to the DSX-3
+//			cross-connect point. Valid values are given in Table 9.8.1-1. Upon ME instantiation for a DS1
+//			interface, the ONU assigns the value 0 for non-power feed type DS1 and the value 6 for power
+//			feed type DS1. Upon ME instantiation for a DS3 interface, the ONU sets this attribute to 0x0F.
+//			(R,-W) (optional) (1-byte)
 //
 //		Ds1 Mode
+//			This attribute specifies the mode of a DS1. Valid values are as follows.
+//
 //			In the event of conflicting values between this attribute and the (also optional) line length
 //			attribute, the line length attribute is taken to be valid. This permits the separation of line
 //			build-out (LBO) and power settings from smart jack and FDL behaviour. Upon ME instantiation, the
 //			ONU sets this attribute to 0. (R,-W) (optional) (1-byte)
 //
 //		Arc
-//			ARC:	See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Arc Interval
-//			ARC interval: See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Line Type
+//			This attribute specifies the line type used in a DS3 or E3 application or when the sensed type
+//			of the PPTP is configurable. Valid values are as follows.
+//
+//			0	Other
+//
+//			1	ds3 m23
+//
+//			2	ds3 syntran
+//
+//			3	ds3 Cbit parity
+//
+//			4	ds3 clear channel
+//
+//			5	e3 framed
+//
+//			6	e3 plcp
+//
+//			7	DS1
+//
+//			8	E1
+//
+//			9	J1
+//
 //			(R,-W) (mandatory for DS3, E3 and multi-configuration interfaces, not applicable to other
 //			interfaces) (1-byte)
 //
diff --git a/generated/physicalpathterminationpointethernetuni.go b/generated/physicalpathterminationpointethernetuni.go
index 063e742..c72fbf0 100644
--- a/generated/physicalpathterminationpointethernetuni.go
+++ b/generated/physicalpathterminationpointethernetuni.go
@@ -27,11 +27,11 @@
 
 // PhysicalPathTerminationPointEthernetUniClassID is the 16-bit ID for the OMCI
 // Managed entity Physical path termination point Ethernet UNI
-const PhysicalPathTerminationPointEthernetUniClassID ClassID = ClassID(11)
+const PhysicalPathTerminationPointEthernetUniClassID = ClassID(11) // 0x000b
 
 var physicalpathterminationpointethernetuniBME *ManagedEntityDefinition
 
-// PhysicalPathTerminationPointEthernetUni (class ID #11)
+// PhysicalPathTerminationPointEthernetUni (Class ID: #11 / 0x000b)
 //	This ME represents the point at an Ethernet UNI where the physical path terminates and Ethernet
 //	physical level functions are performed.
 //
@@ -55,66 +55,136 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. This 2 byte
-//			number indicates the physical position of the UNI. The first byte is the slot ID (defined in
-//			clause 9.1.5). The second byte is the port ID, with the range 1..255. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. This 2 byte number indicates the
+//			physical position of the UNI. The first byte is the slot ID (defined in clause 9.1.5). The
+//			second byte is the port ID, with the range 1..255. (R) (mandatory) (2-bytes)
 //
 //		Expected Type
+//			This attribute supports pre-provisioning. It is coded as follows:
+//
+//			0	Autosense
+//
+//			1 to 254	One of the values from Table-9.1.5-1 that is compatible with an Ethernet circuit pack
+//
 //			Upon ME instantiation, the ONU sets this attribute to 0. (R,-W) (mandatory) (1-byte)
 //
 //		Sensed Type
+//			When a circuit pack is present, this attribute represents its type as one of the values from
+//			Table-9.1.5-1. If the value of the expected type is not 0, then the value of the sensed type
+//			should be the same as the value of the expected type. Upon ME instantiation, the ONU sets this
+//			attribute to 0. See also the note in the following AVC table.
+//
 //			(R) (mandatory if the ONU supports circuit packs with configurable interface types, e.g., 10/100
 //			BASE-T card) (1-byte)
 //
 //		Auto Detection Configuration
+//			This attribute sets the following Ethernet port configuration.
+//
 //			Upon ME instantiation, the ONU sets this attribute to 0. (R,-W) (mandatory for interfaces with
 //			autodetection options) (1-byte)
 //
 //		Ethernet Loopback Configuration
+//			This attribute sets the following Ethernet loopback configuration.
+//
+//			0	No loopback
+//
+//			3	Loop 3, loopback of downstream traffic after PHY transceiver. Loop-3 is depicted in Figure
+//			9.5.1-1.
+//
+//			Note that normal bridge behaviour may defeat the loopback signal unless broadcast MAC addresses
+//			are used. Although it does not reach the physical interface, [IEEE 802.1ag] loopback is
+//			preferred.
+//
 //			Upon ME instantiation, the ONU sets this attribute to 0. (R,-W) (mandatory) (1-byte)
 //
 //		Administrative State
-//			Administrative state: This attribute locks (1) and unlocks (0) the functions performed by this
-//			ME. Administrative state is further described in clause A.1.6. (R,-W) (mandatory) (1-byte)
+//			This attribute locks (1) and unlocks (0) the functions performed by this ME. Administrative
+//			state is further described in clause A.1.6. (R,-W) (mandatory) (1-byte)
 //
 //		Operational State
-//			Operational state: This attribute indicates whether the ME is capable of performing its
-//			function. Valid values are enabled (0) and disabled (1). (R) (optional) (1-byte)
+//			This attribute indicates whether the ME is capable of performing its function. Valid values are
+//			enabled (0) and disabled (1). (R) (optional) (1-byte)
 //
 //		Configuration Ind
+//			This attribute indicates the configuration status of the Ethernet UNI.
+//
+//			0x01	10BASE-T full duplex
+//
+//			0x02	100BASE-T full duplex
+//
+//			0x03	Gigabit Ethernet full duplex
+//
+//			0x04	10Gb/s Ethernet full duplex
+//
+//			0x05	2.5Gb/s Ethernet full duplex
+//
+//			0x06	5Gb/s Ethernet full duplex
+//
+//			0x07	25Gb/s Ethernet full duplex
+//
+//			0x08	40Gb/s Ethernet full duplex
+//
+//			0x11	10BASE-T half duplex
+//
+//			0x12	100BASE-T half duplex
+//
+//			0x13	Gigabit Ethernet half duplex
+//
 //			The value 0 indicates that the configuration status is unknown (e.g., Ethernet link is not
 //			established or the circuit pack is not yet installed). Upon ME instantiation, the ONU sets this
 //			attribute to 0. (R) (mandatory) (1-byte)
 //
 //		Max Frame Size
-//			Max frame size: This attribute denotes the maximum frame size allowed across this interface.
-//			Upon ME instantiation, the ONU sets the attribute to 1518. (R,-W) (mandatory for G-PON, optional
-//			for ITU-T G.986 systems) (2 bytes)
+//			This attribute denotes the maximum frame size allowed across this interface. Upon ME
+//			instantiation, the ONU sets the attribute to 1518. (R,-W) (mandatory for G-PON, optional for
+//			ITU-T G.986 systems) (2 bytes)
 //
 //		Dte Or Dce Ind
+//			This attribute specifies the following Ethernet interface wiring.
+//
+//			0	DCE or MDI-X (default).
+//
+//			1	DTE or MDI.
+//
+//			2	Automatic selection
+//
 //			(R,-W) (mandatory) (1-byte)
 //
 //		Pause Time
-//			Pause time:	This attribute allows the PPTP to ask the subscriber terminal to temporarily suspend
-//			sending data. Units are in pause quanta (1 pause quantum is 512 bit times of the particular
+//			This attribute allows the PPTP to ask the subscriber terminal to temporarily suspend sending
+//			data. Units are in pause quanta (1 pause quantum is 512 bit times of the particular
 //			implementation). Values: 0..0xFFFF. Upon ME instantiation, the ONU sets this attribute to 0.
 //			(R,-W) (optional) (2-bytes)
 //
 //		Bridged Or Ip Ind
+//			This attribute specifies whether the Ethernet interface is bridged or derived from an IP router
+//			function.
+//
+//			0	Bridged
+//
+//			1	IP router
+//
+//			2	Depends on the parent circuit pack. 2 means that the circuit pack's bridged or IP ind
+//			attribute is either 0 or 1.
+//
 //			Upon ME instantiation, the ONU sets this attribute to 2. (R,-W) (optional) (1-byte)
 //
 //		Arc
-//			ARC:	See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Arc Interval
-//			ARC interval: See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Pppoe Filter
-//			PPPoE filter: This attribute controls filtering of PPPoE packets on this Ethernet port. The
-//			value 0 allows packets of all types. The value 1 discards everything but PPPoE packets. The
-//			default value is 0. (R,-W) (optional) (1-byte)
+//			This attribute controls filtering of PPPoE packets on this Ethernet port. The value 0 allows
+//			packets of all types. The value 1 discards everything but PPPoE packets. The default value is 0.
+//			(R,-W) (optional) (1-byte)
 //
 //		Power Control
+//			This attribute controls whether power is provided to an external equipment over the Ethernet
+//			PPTP. The value 1 enables power over the Ethernet port. The default value 0 disables power feed.
+//			(R,-W) (optional) (1-byte)
+//
 //			NOTE - This attribute is the equivalent of the acPSEAdminControl variable defined in clause
 //			30.9.1.2.1 of [IEEE 802.3]. Other variables related to PoE appear in the PoE control ME.
 //
diff --git a/generated/physicalpathterminationpointlctuni.go b/generated/physicalpathterminationpointlctuni.go
index 0e8815a..b6381e6 100644
--- a/generated/physicalpathterminationpointlctuni.go
+++ b/generated/physicalpathterminationpointlctuni.go
@@ -27,11 +27,11 @@
 
 // PhysicalPathTerminationPointLctUniClassID is the 16-bit ID for the OMCI
 // Managed entity Physical path termination point LCT UNI
-const PhysicalPathTerminationPointLctUniClassID ClassID = ClassID(83)
+const PhysicalPathTerminationPointLctUniClassID = ClassID(83) // 0x0053
 
 var physicalpathterminationpointlctuniBME *ManagedEntityDefinition
 
-// PhysicalPathTerminationPointLctUni (class ID #83)
+// PhysicalPathTerminationPointLctUni (Class ID: #83 / 0x0053)
 //	This ME models debug access to the ONU from any physical or logical port, for example, via a
 //	dedicated LCT UNI, via ordinary subscriber UNIs, or via the IP host config ME.
 //
@@ -63,18 +63,18 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. This 2-byte
-//			number indicates the physical position of the UNI. The first byte is the slot ID (defined in
-//			clause 9.1.5). The second byte is the port ID, with the range 1..255. If the LCT UNI is
-//			associated with the ONU as a whole, its ME ID should be 0. (R) (mandatory) (2 bytes)
+//			This attribute uniquely identifies each instance of this ME. This 2-byte number indicates the
+//			physical position of the UNI. The first byte is the slot ID (defined in clause 9.1.5). The
+//			second byte is the port ID, with the range 1..255. If the LCT UNI is associated with the ONU as
+//			a whole, its ME ID should be 0. (R) (mandatory) (2 bytes)
 //
 //		Administrative State
-//			Administrative state: This attribute locks (1) and unlocks (0) the functions performed by this
-//			ME. Administrative state is described generically in clause-A.1.6. The LCT has additional
-//			administrative state behaviour. When the administrative state is set to lock, debug access
-//			through all physical or logical means is blocked, except that the operation of a possible ONU
-//			remote debug ME is not affected. Administrative lock of ME instance 0 overrides administrative
-//			lock of any other PPTP LCT UNIs that may exist. (R, W) (mandatory) (1-byte)
+//			This attribute locks (1) and unlocks (0) the functions performed by this ME. Administrative
+//			state is described generically in clause-A.1.6. The LCT has additional administrative state
+//			behaviour. When the administrative state is set to lock, debug access through all physical or
+//			logical means is blocked, except that the operation of a possible ONU remote debug ME is not
+//			affected. Administrative lock of ME instance 0 overrides administrative lock of any other PPTP
+//			LCT UNIs that may exist. (R, W) (mandatory) (1-byte)
 //
 type PhysicalPathTerminationPointLctUni struct {
 	ManagedEntityDefinition
diff --git a/generated/physicalpathterminationpointmocauni.go b/generated/physicalpathterminationpointmocauni.go
index 59652da..cb35f78 100644
--- a/generated/physicalpathterminationpointmocauni.go
+++ b/generated/physicalpathterminationpointmocauni.go
@@ -27,11 +27,11 @@
 
 // PhysicalPathTerminationPointMocaUniClassID is the 16-bit ID for the OMCI
 // Managed entity Physical path termination point MoCA UNI
-const PhysicalPathTerminationPointMocaUniClassID ClassID = ClassID(162)
+const PhysicalPathTerminationPointMocaUniClassID = ClassID(162) // 0x00a2
 
 var physicalpathterminationpointmocauniBME *ManagedEntityDefinition
 
-// PhysicalPathTerminationPointMocaUni (class ID #162)
+// PhysicalPathTerminationPointMocaUni (Class ID: #162 / 0x00a2)
 //	This ME represents an MoCA UNI, where physical paths terminate and physical path level functions
 //	are performed.
 //
@@ -54,69 +54,83 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. This 2-byte
-//			number is directly associated with the physical position of the UNI. The first byte is the slot
-//			ID (defined in clause 9.1.5). The second byte is the port ID, with the range 1..255. (R)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. This 2-byte number is directly
+//			associated with the physical position of the UNI. The first byte is the slot ID (defined in
+//			clause 9.1.5). The second byte is the port ID, with the range 1..255. (R) (mandatory) (2-bytes)
 //
 //		Loopback Configuration
+//			0	No loopback
+//
+//			3	Loopback3, loopback of downstream traffic after PHY transceiver, depicted in Figure 9.10.1-1.
+//
 //			Upon ME instantiation, the ONU sets this attribute to 0. (R,-W) (optional) (1-byte)
 //
+//			This attribute sets the MoCA loopback configuration. Note that normal bridge behaviour may
+//			defeat the loopback signal unless broadcast MAC addresses are used.
+//
 //		Administrative State
-//			Administrative state: This attribute locks (1) and unlocks (0) the functions performed by this
-//			ME. Administrative state is further described in clause A.1.6. (R,-W) (mandatory) (1-byte)
+//			This attribute locks (1) and unlocks (0) the functions performed by this ME. Administrative
+//			state is further described in clause A.1.6. (R,-W) (mandatory) (1-byte)
 //
 //		Operational State
-//			Operational state: This attribute indicates whether the ME is capable of performing its
-//			function. Valid values are enabled (0) and disabled (1). (R) (optional) (1-byte)
+//			This attribute indicates whether the ME is capable of performing its function. Valid values are
+//			enabled (0) and disabled (1). (R) (optional) (1-byte)
 //
 //		Max Frame Size
-//			Max frame size: This attribute denotes the maximum frame size allowed across this interface.
-//			Upon ME instantiation, the ONU sets this attribute to 1518. (R,-W) (mandatory) (2-bytes)
+//			This attribute denotes the maximum frame size allowed across this interface. Upon ME
+//			instantiation, the ONU sets this attribute to 1518. (R,-W) (mandatory) (2-bytes)
 //
 //		Arc
-//			ARC:	See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Arc Interval
-//			ARC interval: See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Pppoe Filter
-//			PPPoE filter: This attribute controls filtering of PPPoE packets on this MoCA port. When its
-//			value is 1, all packets other than PPPoE packets are discarded. The default 0 accepts packets of
-//			all types. (R,-W) (optional) (1-byte)
+//			This attribute controls filtering of PPPoE packets on this MoCA port. When its value is 1, all
+//			packets other than PPPoE packets are discarded. The default 0 accepts packets of all types.
+//			(R,-W) (optional) (1-byte)
 //
 //		Network Status
+//			This attribute indicates the networking state of the MoCA interface as follows.
+//
+//			0	The interface has not joined an MoCA network.
+//
+//			1	The interface has joined an MoCA network.
+//
+//			2	The interface has joined an MoCA network and is currently the network coordinator.
+//
 //			(R) (mandatory) (1-byte)
 //
 //		Password
-//			Password:	This attribute specifies the MoCA encryption key. It is an ASCII string of 17 decimal
-//			digits. Upon ME instantiation, the ONU sets this attribute to 17 null bytes. (R,-W) (mandatory)
+//			This attribute specifies the MoCA encryption key. It is an ASCII string of 17 decimal digits.
+//			Upon ME instantiation, the ONU sets this attribute to 17 null bytes. (R,-W) (mandatory)
 //			(17-bytes)
 //
 //		Privacy Enabled
-//			Privacy enabled: This attribute activates (1) link-layer security. The default value 0
-//			deactivates it. (R,-W) (mandatory) (1-byte)
+//			This attribute activates (1) link-layer security. The default value 0 deactivates it. (R,-W)
+//			(mandatory) (1-byte)
 //
 //		Minimum Bandwidth Alarm Threshold
-//			Minimum bandwidth alarm threshold: This attribute specifies the minimum desired PHY link
-//			bandwidth between two nodes. If the actual bandwidth is lower, an LL alarm is declared. Valid
-//			values are 0 to 0x0410 (260-Mbit/s) in 0.25-Mbit/s increments. The default value is 0x02D0
-//			(180-Mbit/s). The value 0 disables the threshold. (R,-W) (optional) (2-bytes)
+//			This attribute specifies the minimum desired PHY link bandwidth between two nodes. If the actual
+//			bandwidth is lower, an LL alarm is declared. Valid values are 0 to 0x0410 (260-Mbit/s) in
+//			0.25-Mbit/s increments. The default value is 0x02D0 (180-Mbit/s). The value 0 disables the
+//			threshold. (R,-W) (optional) (2-bytes)
 //
 //		Frequency Mask
-//			Frequency mask: This attribute is a bit map of the centre frequencies that the interface is
-//			permitted to use, where each bit represents a centre frequency. The LSB (b[1]) corresponds to
-//			centre frequency 800-MHz. The next significant bit (b[2]) corresponds to centre frequency
-//			825-MHz. The 28th bit (b[28]) corresponds to centre frequency 1500-MHz. The four MSBs are not
-//			used. (R,-W) (optional) (4-bytes)
+//			This attribute is a bit map of the centre frequencies that the interface is permitted to use,
+//			where each bit represents a centre frequency. The LSB (b[1]) corresponds to centre frequency
+//			800-MHz. The next significant bit (b[2]) corresponds to centre frequency 825-MHz. The 28th bit
+//			(b[28]) corresponds to centre frequency 1500-MHz. The four MSBs are not used. (R,-W) (optional)
+//			(4-bytes)
 //
 //		Rf Channel
-//			RF channel:	This attribute reports the frequency to which the MoCA interface is currently tuned,
-//			in megahertz. (R) (mandatory) (2-bytes)
+//			This attribute reports the frequency to which the MoCA interface is currently tuned, in
+//			megahertz. (R) (mandatory) (2-bytes)
 //
 //		Last Operational Frequency
-//			Last operational frequency: This attribute reports the frequency to which the MoCA interface was
-//			tuned when last operational, in megahertz. (R) (mandatory) (2-bytes)
+//			This attribute reports the frequency to which the MoCA interface was tuned when last
+//			operational, in megahertz. (R) (mandatory) (2-bytes)
 //
 type PhysicalPathTerminationPointMocaUni struct {
 	ManagedEntityDefinition
diff --git a/generated/physicalpathterminationpointpotsuni.go b/generated/physicalpathterminationpointpotsuni.go
index bc12ee8..8b7f6c7 100644
--- a/generated/physicalpathterminationpointpotsuni.go
+++ b/generated/physicalpathterminationpointpotsuni.go
@@ -27,11 +27,11 @@
 
 // PhysicalPathTerminationPointPotsUniClassID is the 16-bit ID for the OMCI
 // Managed entity Physical path termination point POTS UNI
-const PhysicalPathTerminationPointPotsUniClassID ClassID = ClassID(53)
+const PhysicalPathTerminationPointPotsUniClassID = ClassID(53) // 0x0035
 
 var physicalpathterminationpointpotsuniBME *ManagedEntityDefinition
 
-// PhysicalPathTerminationPointPotsUni (class ID #53)
+// PhysicalPathTerminationPointPotsUni (Class ID: #53 / 0x0035)
 //	This ME represents a POTS UNI in the ONU, where a physical path terminates and physical path
 //	level functions (analogue telephony) are performed.
 //
@@ -56,9 +56,9 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. This 2-byte
-//			number indicates the physical position of the UNI. The first byte is the slot ID (defined in
-//			clause 9.1.5). The second byte is the port ID, with the range 1..255. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. This 2-byte number indicates the
+//			physical position of the UNI. The first byte is the slot ID (defined in clause 9.1.5). The
+//			second byte is the port ID, with the range 1..255. (R) (mandatory) (2-bytes)
 //
 //		Administrative State
 //			When the administrative state is set to lock, all user functions of this UNI are blocked, and
@@ -66,66 +66,85 @@
 //			default value for this attribute is outside the scope of this Recommendation. (R, W) (mandatory)
 //			(1 byte)
 //
+//			This attribute shuts down (2), locks (1) and unlocks (0) the functions performed by this ME. If
+//			the administrative state is set to shut down while the POTS UNI line state is non-idle, no
+//			action is taken until the POTS UNI line state changes to idle, whereupon the administrative
+//			state changes to locked. If the administrative state is set to shut down and the POTS UNI line
+//			state is already idle, the administrative state is immediately set to locked. In both cases, the
+//			transition from shutting down to locked state is signalled with an AVC.
+//
 //		Deprecated
-//			Deprecated: This attribute is not used and should not be supported. (R,-W) (optional) (2-bytes)
+//			This attribute is not used and should not be supported. (R,-W) (optional) (2-bytes)
 //
 //		Arc
-//			ARC:	See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Arc Interval
-//			ARC interval: See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Impedance
+//			2	C1=150 nF, R1=750 Ohm, R2=270 Ohm
+//
+//			3	C1=115 nF, R1=820 Ohm, R2=220 Ohm
+//
+//			4	C1=230 nF, R1=1050 Ohm, R2=320 Ohm
+//
 //			where C1, R1, and R2 are related as shown in Figure 9.9.1-1. Upon ME instantiation, the ONU sets
 //			this attribute to 0. (R,-W) (optional) (1-byte)
 //
+//			This attribute specifies the impedance for the POTS UNI. Valid values include the following.
+//
+//			0	600 Ohm
+//
+//			1	900 Ohm
+//
+//			The following parameter sets from Annex C of [ETSI TS 101 270-1] are also defined:
+//
 //		Transmission Path
-//			Transmission path: This attribute allows setting the POTS UNI either to full-time on-hook
-//			transmission (0) or part-time on-hook transmission (1). Upon ME instantiation, the ONU sets this
-//			attribute to 0. (R,-W) (optional) (1-byte)
+//			This attribute allows setting the POTS UNI either to full-time on-hook transmission (0) or part-
+//			time on-hook transmission (1). Upon ME instantiation, the ONU sets this attribute to 0. (R,-W)
+//			(optional) (1-byte)
 //
 //		Rx Gain
-//			Rx gain:	This attribute specifies a gain value for the received signal in the form of a 2s
-//			complement number. Valid values are -120 (12.0-dB) to 60 (+6.0-dB). The direction of the
-//			affected signal is in the D to A direction, towards the telephone set. Upon ME instantiation,
-//			the ONU sets this attribute to 0. (R, W) (optional) (1 byte)
+//			This attribute specifies a gain value for the received signal in the form of a 2s complement
+//			number. Valid values are -120 (12.0-dB) to 60 (+6.0-dB). The direction of the affected signal is
+//			in the D to A direction, towards the telephone set. Upon ME instantiation, the ONU sets this
+//			attribute to 0. (R, W) (optional) (1 byte)
 //
 //		Tx Gain
-//			Tx gain:	This attribute specifies a gain value for the transmit signal in the form of a 2s
-//			complement number. Valid values are -120 (12.0-dB) to 60 (+6.0-dB). The direction of the
-//			affected signal is in the A to D direction, away from the telephone set. Upon ME instantiation,
-//			the ONU sets this attribute to 0. (R, W) (optional) (1 byte)
+//			This attribute specifies a gain value for the transmit signal in the form of a 2s complement
+//			number. Valid values are -120 (12.0-dB) to 60 (+6.0-dB). The direction of the affected signal is
+//			in the A to D direction, away from the telephone set. Upon ME instantiation, the ONU sets this
+//			attribute to 0. (R, W) (optional) (1 byte)
 //
 //		Operational State
-//			Operational state: This attribute indicates whether the ME is capable of performing its
-//			function. Valid values are enabled (0) and disabled (1). (R) (optional) (1-byte)
+//			This attribute indicates whether the ME is capable of performing its function. Valid values are
+//			enabled (0) and disabled (1). (R) (optional) (1-byte)
 //
 //		Hook State
-//			Hook state:	This attribute indicates the current state of the subscriber line: 0-= on hook, 1-=
-//			off hook (R) (optional) (1-byte)
+//			This attribute indicates the current state of the subscriber line: 0-= on hook, 1-= off hook (R)
+//			(optional) (1-byte)
 //
 //		Pots Holdover Time
-//			POTS holdover time: This attribute determines the time during which the POTS loop voltage is
-//			held up when a LOS or softswitch connectivity is detected (please refer to the following table
-//			for description of behaviours).. After the specified time elapses, the ONU drops the loop
-//			voltage, and may thereby cause premises intrusion alarm or fire panel circuits to go active.
-//			When the ONU ranges successfully on the PON or softswitch connectivity is restored, it restores
-//			the POTS loop voltage immediately and resets the timer to zero. The attribute is expressed in
-//			seconds. The default value 0 selects the vendor's factory policy. (R,-W) (optional) (2-bytes)
+//			This attribute determines the time during which the POTS loop voltage is held up when a LOS or
+//			softswitch connectivity is detected (please refer to the following table for description of
+//			behaviours).. After the specified time elapses, the ONU drops the loop voltage, and may thereby
+//			cause premises intrusion alarm or fire panel circuits to go active. When the ONU ranges
+//			successfully on the PON or softswitch connectivity is restored, it restores the POTS loop
+//			voltage immediately and resets the timer to zero. The attribute is expressed in seconds. The
+//			default value 0 selects the vendor's factory policy. (R,-W) (optional) (2-bytes)
 //
 //		Nominal Feed Voltage
-//			Nominal feed voltage: This attribute indicates the designed nominal feed voltage of the POTS
-//			loop. It is an absolute value with resolution 1-V. This attribute does not represent the actual
-//			voltage measured on the loop, which is available through the test command. (R,-W) (optional)
-//			(1-byte)
+//			This attribute indicates the designed nominal feed voltage of the POTS loop. It is an absolute
+//			value with resolution 1-V. This attribute does not represent the actual voltage measured on the
+//			loop, which is available through the test command. (R,-W) (optional) (1-byte)
 //
 //		Loss Of Softswitch
-//			Loss of softswitch: This Boolean attribute controls whether the T/R holdover initiation
-//			criteria. False disables loss of softswitch connectivity detection as criteria for initiating
-//			the POTS holdover timer. True enables loss of softswitch connectivity detection as criteria for
-//			initiating the POTS holdover timer. This attribute is optional (if not implemented, the POTS
-//			holdover time is triggered on a LOS when POTS holdover is greater than zero). (R,-W) (optional)
-//			(1-byte)
+//			This Boolean attribute controls whether the T/R holdover initiation criteria. False disables
+//			loss of softswitch connectivity detection as criteria for initiating the POTS holdover timer.
+//			True enables loss of softswitch connectivity detection as criteria for initiating the POTS
+//			holdover timer. This attribute is optional (if not implemented, the POTS holdover time is
+//			triggered on a LOS when POTS holdover is greater than zero). (R,-W) (optional) (1-byte)
 //
 type PhysicalPathTerminationPointPotsUni struct {
 	ManagedEntityDefinition
diff --git a/generated/physicalpathterminationpointreuni.go b/generated/physicalpathterminationpointreuni.go
index 462fad6..ac1492e 100644
--- a/generated/physicalpathterminationpointreuni.go
+++ b/generated/physicalpathterminationpointreuni.go
@@ -27,11 +27,11 @@
 
 // PhysicalPathTerminationPointReUniClassID is the 16-bit ID for the OMCI
 // Managed entity Physical path termination point RE UNI
-const PhysicalPathTerminationPointReUniClassID ClassID = ClassID(314)
+const PhysicalPathTerminationPointReUniClassID = ClassID(314) // 0x013a
 
 var physicalpathterminationpointreuniBME *ManagedEntityDefinition
 
-// PhysicalPathTerminationPointReUni (class ID #314)
+// PhysicalPathTerminationPointReUni (Class ID: #314 / 0x013a)
 //	This ME represents an S'/R' interface in a mid-span PON RE that supports OEO regeneration in at
 //	least one direction, where physical paths terminate and physical path level functions are
 //	performed (transmit or receive).
@@ -71,80 +71,108 @@
 //
 //	Attributes
 //		Managed Entity Id
+//			This attribute uniquely identifies each instance of this ME. This 2-byte number indicates the
+//			physical position of the UNI. The first byte is the slot ID (defined in clause 9.1.5). The
+//			second byte is the port ID, with the range 1..255. (R) (mandatory) (2-bytes)
+//
 //			NOTE 1 - This ME ID may be identical to that of an RE upstream amplifier if it shares the same
 //			physical slot and port.
 //
 //		Administrative State
+//			This attribute locks (1) and unlocks (0) the functions performed by this ME. Administrative
+//			state is further described in clause A.1.6. (R,-W) (mandatory) (1-byte)
+//
 //			NOTE 2 - Administrative lock of a PPTP RE UNI results in loss of signal to any downstream ONUs.
 //
 //		Operational State
-//			Operational state: This attribute indicates whether the ME is capable of performing its
-//			function. Valid values are enabled (0) and disabled (1). (R) (optional) (1-byte)
+//			This attribute indicates whether the ME is capable of performing its function. Valid values are
+//			enabled (0) and disabled (1). (R) (optional) (1-byte)
 //
 //		Arc
-//			ARC:	See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Arc Interval
-//			ARC interval: See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Re Ani_G Pointer
 //			RE ANI-G pointer: This attribute points to an RE ANI-G instance. (R,-W) (mandatory) (2-bytes)
 //
 //		Total Optical Receive Signal Level Table
-//			Total optical receive signal level table: This table attribute reports a series of measurements
-//			of time averaged received upstream optical signal power. The measurement circuit should have a
-//			temporal response similar to a simple 1-pole low pass filter, with an effective time constant of
-//			the order of a GTC frame time. Each table entry has a 2-byte frame counter field (most
-//			significant end), and a 2-byte power measurement field. The frame counter field contains the
-//			least significant 16-bits of the superframe counter received closest to the time of the
-//			measurement. The power measurement field is a 2s complement integer referred to 1-mW (i.e.,
-//			dBm), with 0.002-dB granularity. The RE equipment should add entries to this table as frequently
-//			as is reasonable. The RE should clear the table once it is read by the OLT. (R) (optional) (4-*
-//			N-bytes, where N is the number of measurements present.)
+//			This table attribute reports a series of measurements of time averaged received upstream optical
+//			signal power. The measurement circuit should have a temporal response similar to a simple 1-pole
+//			low pass filter, with an effective time constant of the order of a GTC frame time. Each table
+//			entry has a 2-byte frame counter field (most significant end), and a 2-byte power measurement
+//			field. The frame counter field contains the least significant 16-bits of the superframe counter
+//			received closest to the time of the measurement. The power measurement field is a 2s complement
+//			integer referred to 1-mW (i.e., dBm), with 0.002-dB granularity. (Coding -32768 to +32767, where
+//			0x00 = 0-dBm, 0x03e8 = +2-dBm, etc.) The RE equipment should add entries to this table as
+//			frequently as is reasonable. The RE should clear the table once it is read by the OLT. (R)
+//			(optional) (4-* N-bytes, where N is the number of measurements present.)
 //
 //		Per Burst Receive Signal Level Table
-//			Per burst receive signal level table: This table attribute reports the most recent measurement
-//			of received burst upstream optical signal power. Each table entry has a 2-byte ONU-ID field
-//			(most significant end), and a 2-byte power measurement field. The power measurement field is a
-//			2s complement integer referred to 1-mW (i.e.,-dBm), with 0.002-dB granularity. (R) (optional)
-//			(4-* N-bytes, where N is the number of distinct ONUs connected to the S'/R' interface.)
+//			This table attribute reports the most recent measurement of received burst upstream optical
+//			signal power. Each table entry has a 2-byte ONU-ID field (most significant end), and a 2-byte
+//			power measurement field. The power measurement field is a 2s complement integer referred to 1-mW
+//			(i.e.,-dBm), with 0.002-dB granularity. (Coding -32768 to +32767, where 0x00 = 0-dBm, 0x03e8 =
+//			+2-dBm, etc.) (R) (optional) (4-* N-bytes, where N is the number of distinct ONUs connected to
+//			the S'/R' interface.)
 //
 //		Lower Receive Optical Threshold
-//			Lower receive optical threshold: This attribute specifies the optical level that the RE uses to
-//			declare the burst mode low received optical power alarm. Valid values are  -127-dBm (coded as
-//			254) to 0-dBm (coded as 0) in 0.5-dB increments. The default value 0xFF selects the RE's
-//			internal policy. (R,-W) (optional) (1-byte)
+//			This attribute specifies the optical level that the RE uses to declare the burst mode low
+//			received optical power alarm. Valid values are  -127-dBm (coded as 254) to 0-dBm (coded as 0) in
+//			0.5-dB increments. The default value 0xFF selects the RE's internal policy. (R,-W) (optional)
+//			(1-byte)
 //
 //		Upper Receive Optical Threshold
-//			Upper receive optical threshold: This attribute specifies the optical level that the RE uses to
-//			declare the burst mode high optical power alarm. Valid values are  -127-dBm (coded as 254) to
-//			0-dBm (coded as 0) in 0.5-dB increments. The default value 0xFF selects the RE's internal
-//			policy. (R,-W) (optional) (1-byte)
+//			This attribute specifies the optical level that the RE uses to declare the burst mode high
+//			optical power alarm. Valid values are  -127-dBm (coded as 254) to 0-dBm (coded as 0) in 0.5-dB
+//			increments. The default value 0xFF selects the RE's internal policy. (R,-W) (optional) (1-byte)
 //
 //		Transmit Optical Level
-//			Transmit optical level: This attribute reports the current measurement of the downstream mean
-//			optical launch power. Its value is a 2s complement integer referred to 1-mW (i.e., dBm), with
-//			0.002-dB granularity. (R) (optional) (2-bytes)
+//			This attribute reports the current measurement of the downstream mean optical launch power. Its
+//			value is a 2s complement integer referred to 1-mW (i.e., dBm), with 0.002-dB granularity. (R)
+//			(optional) (2-bytes)
 //
 //		Lower Transmit Power Threshold
-//			Lower transmit power threshold: This attribute specifies the downstream minimum mean optical
-//			launch power at the S'/R' interface that the RE uses to declare the low transmit optical power
-//			alarm. Its value is a 2s complement integer referred to 1-mW (i.e., dBm), with 0.5-dB
-//			granularity. The default value 0x7F selects the RE's internal policy. (R,-W) (optional) (1-byte)
+//			This attribute specifies the downstream minimum mean optical launch power at the S'/R' interface
+//			that the RE uses to declare the low transmit optical power alarm. Its value is a 2s complement
+//			integer referred to 1-mW (i.e., dBm), with 0.5-dB granularity. The default value 0x7F selects
+//			the RE's internal policy. (R,-W) (optional) (1-byte)
 //
 //		Upper Transmit Power Threshold
-//			Upper transmit power threshold: This attribute specifies the downstream maximum mean optical
-//			launch power at the S'/R' interface that the RE uses to declare the high transmit optical power
-//			alarm. Its value is a 2s complement integer referred to 1-mW (i.e., dBm), with 0.5-dB
-//			granularity. The default value 0x7F selects the RE's internal policy. (R,-W) (optional) (1-byte)
+//			This attribute specifies the downstream maximum mean optical launch power at the S'/R' interface
+//			that the RE uses to declare the high transmit optical power alarm. Its value is a 2s complement
+//			integer referred to 1-mW (i.e., dBm), with 0.5-dB granularity. The default value 0x7F selects
+//			the RE's internal policy. (R,-W) (optional) (1-byte)
 //
-//		A Dditional Preamble
-//			Additional preamble: This attribute indicates the number of bytes of PLOu preamble that are
-//			unavoidably consumed while passing the RE. (R) (mandatory) (1-byte)
+//		Additional Preamble
+//			This attribute indicates the number of bytes of PLOu preamble that are unavoidably consumed
+//			while passing the RE. (R) (mandatory) (1-byte)
 //
-//		A Dditional Guard Time
-//			Additional guard time: This attribute indicates the number of bytes of extra guard time that are
-//			needed to ensure correct operation with the RE. (R) (mandatory) (1-byte)
+//		Additional Guard Time
+//			This attribute indicates the number of bytes of extra guard time that are needed to ensure
+//			correct operation with the RE. (R) (mandatory) (1-byte)
+//
+//		Connected Onus Table
+//			s attribute is used to pass ONU ID information of the connected ONUs per RE UNI. The get, get
+//			next sequence must be used with this attribute since its size is unspecified. Upon ME
+//			instantiation, this attribute is an empty list.
+//
+//			Each entry contains:
+//
+//			- ONU ID (2-bytes)
+//
+//			(R) (optional) (2N bytes, where N is the number of-ONUs)
+//
+//		Clear Onu Table
+//			the attribute is used to notify RE to clear the entire Connected ONUs table by OLT. The OLT must
+//			insure that the ONU IDs have been retrieved before clearing the table, or loss of data may
+//			occur.
+//
+//			When the value of the byte is set to 1, the RE clears the entire Connected ONUs table and resets
+//			the byte to 0.
+//
+//			(W) (optional) (1 byte)
 //
 type PhysicalPathTerminationPointReUni struct {
 	ManagedEntityDefinition
@@ -160,7 +188,7 @@
 			GetNext,
 			Set,
 		),
-		AllowedAttributeMask: 0xfffc,
+		AllowedAttributeMask: 0xffff,
 		AttributeDefinitions: AttributeDefinitionMap{
 			0:  Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read), false, false, false, 0),
 			1:  ByteField("AdministrativeState", UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read, Write), false, false, false, 1),
@@ -175,8 +203,10 @@
 			10: Uint16Field("TransmitOpticalLevel", UnsignedIntegerAttributeType, 0x0040, 0, mapset.NewSetWith(Read), false, true, false, 10),
 			11: ByteField("LowerTransmitPowerThreshold", UnsignedIntegerAttributeType, 0x0020, 0, mapset.NewSetWith(Read, Write), false, true, false, 11),
 			12: ByteField("UpperTransmitPowerThreshold", UnsignedIntegerAttributeType, 0x0010, 0, mapset.NewSetWith(Read, Write), false, true, false, 12),
-			13: ByteField("ADditionalPreamble", UnsignedIntegerAttributeType, 0x0008, 0, mapset.NewSetWith(Read), false, false, false, 13),
-			14: ByteField("ADditionalGuardTime", UnsignedIntegerAttributeType, 0x0004, 0, mapset.NewSetWith(Read), false, false, false, 14),
+			13: ByteField("AdditionalPreamble", UnsignedIntegerAttributeType, 0x0008, 0, mapset.NewSetWith(Read), false, false, false, 13),
+			14: ByteField("AdditionalGuardTime", UnsignedIntegerAttributeType, 0x0004, 0, mapset.NewSetWith(Read), false, false, false, 14),
+			15: TableField("ConnectedOnusTable", TableAttributeType, 0x0002, TableInfo{nil, 2}, mapset.NewSetWith(Read), false, true, false, 15),
+			16: TableField("ClearOnuTable", TableAttributeType, 0x0001, TableInfo{nil, 1}, mapset.NewSetWith(Write), false, true, false, 16),
 		},
 		Access:  CreatedByOnu,
 		Support: UnknownSupport,
diff --git a/generated/physicalpathterminationpointvideoani.go b/generated/physicalpathterminationpointvideoani.go
index 39d03e6..c0728fe 100644
--- a/generated/physicalpathterminationpointvideoani.go
+++ b/generated/physicalpathterminationpointvideoani.go
@@ -27,11 +27,11 @@
 
 // PhysicalPathTerminationPointVideoAniClassID is the 16-bit ID for the OMCI
 // Managed entity Physical path termination point video ANI
-const PhysicalPathTerminationPointVideoAniClassID ClassID = ClassID(90)
+const PhysicalPathTerminationPointVideoAniClassID = ClassID(90) // 0x005a
 
 var physicalpathterminationpointvideoaniBME *ManagedEntityDefinition
 
-// PhysicalPathTerminationPointVideoAni (class ID #90)
+// PhysicalPathTerminationPointVideoAni (Class ID: #90 / 0x005a)
 //	This ME represents an RF video ANI in the ONU, where physical paths terminate and physical path
 //	level functions are performed.
 //
@@ -55,69 +55,182 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. This 2-byte
-//			number indicates the physical position of the ANI. The first byte is the slot ID (defined in
-//			clause 9.1.5). The second byte is the port ID, with the range 1..255. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. This 2-byte number indicates the
+//			physical position of the ANI. The first byte is the slot ID (defined in clause 9.1.5). The
+//			second byte is the port ID, with the range 1..255. (R) (mandatory) (2-bytes)
 //
 //		Administrative State
-//			Administrative state: This attribute locks (1) and unlocks (0) the functions performed by this
-//			ME. Administrative state is further described in clause-A.1.6. (R,-W) (mandatory) (1-byte)
+//			This attribute locks (1) and unlocks (0) the functions performed by this ME. Administrative
+//			state is further described in clause-A.1.6. (R,-W) (mandatory) (1-byte)
 //
 //		Operational State
-//			Operational state: This attribute indicates whether the ME is capable of performing its
-//			function. Valid values are enabled (0) and disabled (1). (R) (optional) (1-byte)
+//			This attribute indicates whether the ME is capable of performing its function. Valid values are
+//			enabled (0) and disabled (1). (R) (optional) (1-byte)
 //
 //		Arc
-//			ARC:	See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Arc Interval
-//			ARC interval: See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Frequency Range Low
+//			This attribute indicates the lower of the two possible frequency ranges supported. Different
+//			frequency ranges are indicated by code points:
+//
+//			0	No low band
+//
+//			1	50..550 MHz
+//
+//			2	50..750 MHz
+//
+//			3	50..870 MHz
+//
+//			4..255	Reserved
+//
 //			(R) (mandatory) (1-byte)
 //
 //		Frequency Range High
+//			This attribute indicates the higher of the two frequency ranges supported. Different frequency
+//			ranges are indicated by code points:
+//
+//			0	No high band
+//
+//			1	550..750 MHz
+//
+//			2	550..870 MHz
+//
+//			3	950..2050 MHz
+//
+//			4	2150..3250 MHz
+//
+//			5	950..3250 MHz
+//
+//			6..255	Reserved
+//
 //			(R) (mandatory) (1-byte)
 //
 //		Signal Capability
+//			0	No signal level measurement capability
+//
+//			1	Total optical power level
+//
+//			2	Fixed frequency pilot tone power level
+//
+//			3	Total optical power level and fixed frequency pilot tone power level
+//
+//			4	Variable frequency pilot tone power level
+//
+//			5	Total optical power level and variable frequency pilot tone power level
+//
+//			6	Broadband RF power level
+//
+//			7	Total optical power level and broadband RF power level
+//
+//			8..255	Reserved
+//
 //			(R) (mandatory) (1-byte)
 //
+//			This attribute indicates the capability of the ONU to measure the video signal level.
+//			Capabilities are indicated by code points, as follows.
+//
 //		Optical Signal Level
+//			This attribute is an unsigned integer that returns the current measurement of the total optical
+//			signal level. The unit of this attribute is decibel-microwatt optical.
+//
+//			o	If signal capability-= 0, 2, 4 or 6, this attribute is undefined.
+//
+//			o	If signal capability-=1, 3, 5 or 7, this attribute describes the total optical power that is
+//			generating photocurrent on the receiver.
+//
 //			(R) (optional) (1-byte)
 //
 //		Pilot Signal Level
+//			This attribute indicates the current measurement of the pilot signal level or broadband RF
+//			level. The unit of this attribute is decibel-microvolt at the RF video service port.
+//
+//			o	If signal capability-= 0 or 1, then this attribute is undefined.
+//
+//			o	If signal capability-= 2, 3, 4 or 5, this attribute reports the pilot signal level at the
+//			output of the video UNI.
+//
+//			o	If signal capability-= 6 or 7, this attribute reports the total RF power level at the output
+//			of the video UNI.
+//
 //			(R) (optional) (1-byte)
 //
 //		Signal Level Min
-//			Signal level min: This attribute indicates the minimum optical RF power per channel that results
-//			in a CNR of 47-dBc for a channel of 4.5 MHz bandwidth at a receive optical power of -5-dBm. The
-//			unit of this attribute is decibel-microwatt optical. (R) (mandatory) (1-byte)
+//			This attribute indicates the minimum optical RF power per channel that results in a CNR of
+//			47-dBc for a channel of 4.5 MHz bandwidth at a receive optical power of -5-dBm. The unit of this
+//			attribute is decibel-microwatt optical. (R) (mandatory) (1-byte)
 //
 //		Signal Level Max
-//			Signal level max: This attribute indicates the maximum optical RF power per channel that results
-//			in a CTB of -57-dBc for an 80-channel ensemble of carriers at a perchannel optical modulation
-//			index (OMI) of 3.5%. The unit of this attribute is decibel-microwatt optical. (R) (mandatory)
-//			(1-byte)
+//			This attribute indicates the maximum optical RF power per channel that results in a CTB of
+//			-57-dBc for an 80-channel ensemble of carriers at a perchannel optical modulation index (OMI) of
+//			3.5%. The unit of this attribute is decibel-microwatt optical. (R) (mandatory) (1-byte)
 //
 //		Pilot Frequency
+//			This attribute specifies the frequency of the pilot channel receiver. The unit of this attribute
+//			is hertz.
+//
+//			o	If signal capability-= 0, 1, 6 or 7, this attribute is undefined.
+//
+//			o	If signal capability-= 2 or 3, this attribute is functionally RO.
+//
+//			o	If signal capability-= 4 or 5, this attribute is RW.
+//
 //			(R,-W) (optional) (4-bytes)
 //
 //		Agc Mode
+//			This attribute allows the discovery and configuration of the ONU's AGC capabilities. The
+//			attribute contains a code point for several AGC types. The ONU displays the currently used AGC
+//			mode. The OLT can discover new modes via the set command; the ONU denies attempts to set an
+//			unsupported mode. The code points are as follows.
+//
+//			0	No AGC
+//
+//			1	Broadband RF AGC
+//
+//			2	Optical AGC
+//
+//			3..255	Reserved
+//
 //			(R,-W) (optional) (1-byte)
 //
 //		Agc Setting
+//			This attribute indicates the measurement offset that the ONU should use in AGC. The attribute
+//			has a step size of 0.1-dB, represented as a signed integer.
+//
+//			The theoretical nominal RF signal is 80 channels of NTSC video, each with a per-channel OMI of
+//			3.5%. An ONU presented with such a signal should produce its specified output when this
+//			attribute is set to zero.
+//
+//			If total optical power is used for AGC, this attribute provides the OMI offset for any NTSC
+//			carriers present from the theoretical 3.5% value. For example, if the actual signal uses an OMI
+//			of 7.0% per channel (3-dB higher), then the ONU should be given an AGC setting of 30 (coded
+//			0x1E).
+//
+//			If broadband RF power is used for AGC, this attribute provides the total power offset for any
+//			NTSC carriers present from the theoretical 80-channel value. For example, if an actual signal
+//			contains 40 NTSC channels (3-dB lower), then the ONU should be given an AGC setting of -30
+//			(coded 0xE2).
+//
 //			(R,-W) (optional) (1-byte)
 //
 //		Video Lower Optical Threshold
+//			This attribute specifies the optical level used to declare the video OOR low alarm. Valid values
+//			are -12 to +6-dBm in 0.1-dB increments, represented as a 2s complement integer. (Coding -120 to
+//			+60, where 0x00-= 0-dBm, 0x88-= -12.0 dBm, etc.) Upon ME instantiation, the ONU sets this
+//			attribute to 0xA1 (-9.5-dBm). (R,-W) (optional) (1-byte)
+//
 //			NOTE - Because the power measurement returned in the optical signal level attribute has a
 //			resolution of 1-dB, it is possible that the measured value could appear to be in-range, even
 //			though an out-of-range alarm has been declared against a threshold with 0.1-dB resolution.
 //
 //		Video Upper Optical Threshold
-//			Video upper optical threshold: This attribute specifies the optical level used to declare the
-//			video OOR high alarm. Valid values are -12 to +6-dBm in 0.1-dB increments, represented as a 2s
-//			complement integer. (Coding -120 to +60, 0x00-= 0-dBm, 0x88-= -12.0-dBm, etc.) Upon ME
-//			instantiation, the ONU sets this attribute to 0x19 (+2.5-dBm). (R,-W) (optional) (1-byte)
+//			This attribute specifies the optical level used to declare the video OOR high alarm. Valid
+//			values are -12 to +6-dBm in 0.1-dB increments, represented as a 2s complement integer. (Coding
+//			-120 to +60, 0x00-= 0-dBm, 0x88-= -12.0-dBm, etc.) Upon ME instantiation, the ONU sets this
+//			attribute to 0x19 (+2.5-dBm). (R,-W) (optional) (1-byte)
 //
 type PhysicalPathTerminationPointVideoAni struct {
 	ManagedEntityDefinition
diff --git a/generated/physicalpathterminationpointvideouni.go b/generated/physicalpathterminationpointvideouni.go
index fbd31d0..40d8f61 100644
--- a/generated/physicalpathterminationpointvideouni.go
+++ b/generated/physicalpathterminationpointvideouni.go
@@ -27,11 +27,11 @@
 
 // PhysicalPathTerminationPointVideoUniClassID is the 16-bit ID for the OMCI
 // Managed entity Physical path termination point video UNI
-const PhysicalPathTerminationPointVideoUniClassID ClassID = ClassID(82)
+const PhysicalPathTerminationPointVideoUniClassID = ClassID(82) // 0x0052
 
 var physicalpathterminationpointvideouniBME *ManagedEntityDefinition
 
-// PhysicalPathTerminationPointVideoUni (class ID #82)
+// PhysicalPathTerminationPointVideoUni (Class ID: #82 / 0x0052)
 //	This ME represents an RF video UNI in the ONU, where physical paths terminate and physical path
 //	level functions are performed.
 //
@@ -55,28 +55,28 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. This 2-byte
-//			number indicates the physical position of the UNI. The first byte is the slot ID (defined in
-//			clause 9.1.5). The second byte is the port ID, with the range 1..255. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. This 2-byte number indicates the
+//			physical position of the UNI. The first byte is the slot ID (defined in clause 9.1.5). The
+//			second byte is the port ID, with the range 1..255. (R) (mandatory) (2-bytes)
 //
 //		Administrative State
-//			Administrative state: This attribute locks (1) and unlocks (0) the functions performed by this
-//			ME. Administrative state is further described in clause A.1.6. (R,-W) (mandatory) (1-byte)
+//			This attribute locks (1) and unlocks (0) the functions performed by this ME. Administrative
+//			state is further described in clause A.1.6. (R,-W) (mandatory) (1-byte)
 //
 //		Operational State
-//			Operational state: This attribute indicates whether the ME is capable of performing its
-//			function. Valid values are enabled (0) and disabled (1). (R) (optional) (1-byte)
+//			This attribute indicates whether the ME is capable of performing its function. Valid values are
+//			enabled (0) and disabled (1). (R) (optional) (1-byte)
 //
 //		Arc
-//			ARC:	See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Arc Interval
-//			ARC interval: See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Power Control
-//			Power control: This attribute controls whether power is provided from the ONU to an external
-//			equipment over the video PPTP. Value 1 enables power over coaxial cable. The default value 0
-//			disables power feed. (R,-W) (optional) (1-byte)
+//			This attribute controls whether power is provided from the ONU to an external equipment over the
+//			video PPTP. Value 1 enables power over coaxial cable. The default value 0 disables power feed.
+//			(R,-W) (optional) (1-byte)
 //
 type PhysicalPathTerminationPointVideoUni struct {
 	ManagedEntityDefinition
diff --git a/generated/physicalpathterminationpointxdslunipart1.go b/generated/physicalpathterminationpointxdslunipart1.go
index fa883bc..cec0633 100644
--- a/generated/physicalpathterminationpointxdslunipart1.go
+++ b/generated/physicalpathterminationpointxdslunipart1.go
@@ -27,11 +27,11 @@
 
 // PhysicalPathTerminationPointXdslUniPart1ClassID is the 16-bit ID for the OMCI
 // Managed entity Physical path termination point xDSL UNI part 1
-const PhysicalPathTerminationPointXdslUniPart1ClassID ClassID = ClassID(98)
+const PhysicalPathTerminationPointXdslUniPart1ClassID = ClassID(98) // 0x0062
 
 var physicalpathterminationpointxdslunipart1BME *ManagedEntityDefinition
 
-// PhysicalPathTerminationPointXdslUniPart1 (class ID #98)
+// PhysicalPathTerminationPointXdslUniPart1 (Class ID: #98 / 0x0062)
 //	This ME represents the point where physical paths terminate on an xDSL CO modem (xTU-C). The
 //	xDSL ME family is used for ADSL VDSL2 and FAST services. A legacy family of VDSL MEs remains
 //	valid for ITUT G.993.1 VDSL, if needed. It is documented in [ITUT G.983.2].
@@ -55,38 +55,43 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID:	This attribute uniquely identifies each instance of this ME. This 2 byte
-//			number indicates the physical position of the UNI. The six LSBs of the first byte are the slot
-//			ID, defined in clause 9.1.5. The two MSBs indicate the channel number in some of the implicitly
-//			linked MEs, and must be 0 in the PPTP itself. This reduces the possible number of physical slots
-//			to 64. The second byte is the port ID, with the range 1..255. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. This 2 byte number indicates the
+//			physical position of the UNI. The six LSBs of the first byte are the slot ID, defined in clause
+//			9.1.5. The two MSBs indicate the channel number in some of the implicitly linked MEs, and must
+//			be 0 in the PPTP itself. This reduces the possible number of physical slots to 64. The second
+//			byte is the port ID, with the range 1..255. (R) (mandatory) (2-bytes)
 //
 //		Loopback Configuration
+//			This attribute represents the loopback configuration of this physical interface.
+//
+//			0	No loopback
+//
+//			1	Loopback2 - a loopback at the ONU towards the OLT. The OLT can execute a physical level
+//			loopback test after loopback2 is set.
+//
 //			Upon ME instantiation, the ONU sets this attribute to 0. (R,-W) (mandatory) (1-byte)
 //
 //		Administrative State
-//			Administrative state: This attribute locks (1) and unlocks (0) the functions performed by this
-//			ME. Administrative state is further described in clause A.1.6. (R,-W) (mandatory) (1-byte)
+//			This attribute locks (1) and unlocks (0) the functions performed by this ME. Administrative
+//			state is further described in clause A.1.6. (R,-W) (mandatory) (1-byte)
 //
 //		Operational State
-//			Operational state: This attribute indicates whether the ME is capable of performing its
-//			function. Valid values are enabled (0) and disabled (1). (R) (optional) (1-byte)
+//			This attribute indicates whether the ME is capable of performing its function. Valid values are
+//			enabled (0) and disabled (1). (R) (optional) (1-byte)
 //
 //		Xdsl Line Configuration Profile
-//			xDSL line configuration profile: This attribute points to an instance of the xDSL line
-//			configuration profiles (part 1, 2 and 3) MEs, and if necessary, also to VDSL2 line configuration
-//			extensions (1 and 2) MEs, also to vectoring line configuration extension MEs. Upon ME
-//			instantiation, the ONU sets this attribute to 0, a null pointer. (R,-W) (mandatory) (2-bytes)
+//			This attribute points to an instance of the xDSL line configuration profiles (part 1, 2 and 3)
+//			MEs, and if necessary, also to VDSL2 line configuration extensions (1 and 2) MEs, also to
+//			vectoring line configuration extension MEs. Upon ME instantiation, the ONU sets this attribute
+//			to 0, a null pointer. (R,-W) (mandatory) (2-bytes)
 //
 //		Xdsl Subcarrier Masking Downstream Profile
-//			xDSL subcarrier masking downstream profile: This attribute points to an instance of the xDSL
-//			subcarrier masking downstream profile ME. Upon ME instantiation, the ONU sets this attribute to
-//			0, a null pointer. (R,-W) (mandatory) (2-bytes)
+//			This attribute points to an instance of the xDSL subcarrier masking downstream profile ME. Upon
+//			ME instantiation, the ONU sets this attribute to 0, a null pointer. (R,-W) (mandatory) (2-bytes)
 //
 //		Xdsl Subcarrier Masking Upstream Profile
-//			xDSL subcarrier masking upstream profile: This attribute points to an instance of the xDSL
-//			subcarrier masking upstream profile ME. Upon ME instantiation, the ONU sets this attribute to 0,
-//			a null pointer. (R,-W) (mandatory) (2-bytes)
+//			This attribute points to an instance of the xDSL subcarrier masking upstream profile ME. Upon ME
+//			instantiation, the ONU sets this attribute to 0, a null pointer. (R,-W) (mandatory) (2-bytes)
 //
 //		Xdsl Downstream Power Spectral Density Psd Mask Profile
 //			xDSL downstream power spectral density (PSD) mask profile: This attribute points to an instance
@@ -94,31 +99,41 @@
 //			ONU sets this attribute to 0, a null pointer. (R,-W) (mandatory) (2-bytes)
 //
 //		Xdsl Downstream Rfi Bands Profile
-//			xDSL downstream RFI bands profile: This attribute points to an instance of the xDSL downstream
-//			RFI bands profile ME. Upon ME instantiation, the ONU sets this attribute to 0, a null pointer.
-//			(R,-W) (mandatory) (2-bytes)
+//			This attribute points to an instance of the xDSL downstream RFI bands profile ME. Upon ME
+//			instantiation, the ONU sets this attribute to 0, a null pointer. (R,-W) (mandatory) (2-bytes)
 //
 //		Arc
-//			ARC:	See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Arc Interval
-//			ARC interval: See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Modem Type
+//			This attribute specifies the modem type. If the hardware cannot support the requested modem
+//			type, the ONU should deny the provisioning command. For backward compatibility, the attribute is
+//			optional, with a default of ATM.
+//
+//			0	undefined
+//
+//			1	ATM (default)
+//
+//			2	PTM (Ethernet)
+//
+//			(R,-W) (optional) (1-byte)
+//
 //			NOTE - Many newer VDSL2 chip sets support only PTM. The ATM default is retained for backward
 //			compatibility, but implementers should be aware that the default may need to be overridden by
 //			provisioning before the xDSL UNI can be brought into service.
 //
 //		Upstream Psd Mask Profile
-//			Upstream PSD mask profile: This attribute points to an instance of the xDSL PSD mask profile
-//			that defines upstream parameters. Upon ME instantiation, the ONU sets this attribute to 0, a
-//			null pointer. (R,-W) (optional) (2-bytes)
+//			This attribute points to an instance of the xDSL PSD mask profile that defines upstream
+//			parameters. Upon ME instantiation, the ONU sets this attribute to 0, a null pointer. (R,-W)
+//			(optional) (2-bytes)
 //
 //		Network Specific Extensions Pointer
-//			Network specific extensions pointer: This attribute points to a network address ME that contains
-//			the path and name of a file containing network specific parameters for the associated UNI. Upon
-//			ME instantiation, the ONU sets this attribute to 0xFFFF, a null pointer. (R,-W) (optional)
-//			(2-bytes)
+//			This attribute points to a network address ME that contains the path and name of a file
+//			containing network specific parameters for the associated UNI. Upon ME instantiation, the ONU
+//			sets this attribute to 0xFFFF, a null pointer. (R,-W) (optional) (2-bytes)
 //
 type PhysicalPathTerminationPointXdslUniPart1 struct {
 	ManagedEntityDefinition
diff --git a/generated/physicalpathterminationpointxdslunipart2.go b/generated/physicalpathterminationpointxdslunipart2.go
index 4de399d..6aca5a1 100644
--- a/generated/physicalpathterminationpointxdslunipart2.go
+++ b/generated/physicalpathterminationpointxdslunipart2.go
@@ -27,11 +27,11 @@
 
 // PhysicalPathTerminationPointXdslUniPart2ClassID is the 16-bit ID for the OMCI
 // Managed entity Physical path termination point xDSL UNI part 2
-const PhysicalPathTerminationPointXdslUniPart2ClassID ClassID = ClassID(99)
+const PhysicalPathTerminationPointXdslUniPart2ClassID = ClassID(99) // 0x0063
 
 var physicalpathterminationpointxdslunipart2BME *ManagedEntityDefinition
 
-// PhysicalPathTerminationPointXdslUniPart2 (class ID #99)
+// PhysicalPathTerminationPointXdslUniPart2 (Class ID: #99 / 0x0063)
 //	This ME represents the point in the ONU where physical paths terminate on an xDSL CO modem
 //	(xTU-C). Standards and chip sets support several forms of DSL, including VDSL2, and the xDSL ME
 //	family is used for all of them, with specific extensions for technology variations.
@@ -44,33 +44,35 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP xDSL UNI part 1. (R)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP xDSL UNI part 1. (R) (mandatory) (2-bytes)
+//
+//			Each of the following eight attributes is a pointer to an xDSL channel configuration profile ME.
+//			In each case, the default value 0, set when the ME is auto-created, is a null pointer.
 //
 //		Xdsl Channel Configuration Profile For Bearer Channel 0 Downstream
-//			xDSL channel configuration profile for bearer channel 0 downstream: 	(R,-W) (optional) (2-bytes)
+//				(R,-W) (optional) (2-bytes)
 //
 //		Xdsl Channel Configuration Profile For Bearer Channel 1 Downstream
-//			xDSL channel configuration profile for bearer channel 1 downstream: 	(R,-W) (optional) (2-bytes)
+//				(R,-W) (optional) (2-bytes)
 //
 //		Xdsl Channel Configuration Profile For Bearer Channel 2 Downstream
-//			xDSL channel configuration profile for bearer channel 2 downstream: 	(R,-W) (optional) (2-bytes)
+//				(R,-W) (optional) (2-bytes)
 //
 //		Xdsl Channel Configuration Profile For Bearer Channel 3 Downstream
-//			xDSL channel configuration profile for bearer channel 3 downstream: 	(R,-W) (optional) (2-bytes)
+//				(R,-W) (optional) (2-bytes)
 //
 //		Xdsl Channel Configuration Profile For Bearer Channel 0 Upstream
-//			xDSL channel configuration profile for bearer channel 0 upstream: 	(R,-W) (optional) (2-bytes)
+//				(R,-W) (optional) (2-bytes)
 //
 //		Xdsl Channel Configuration Profile For Bearer Channel 1 Upstream
-//			xDSL channel configuration profile for bearer channel 1 upstream: 	(R,-W) (optional) (2-bytes)
+//				(R,-W) (optional) (2-bytes)
 //
 //		Xdsl Channel Configuration Profile For Bearer Channel 2 Upstream
-//			xDSL channel configuration profile for bearer channel 2 upstream: 	(R,-W) (optional) (2-bytes)
+//				(R,-W) (optional) (2-bytes)
 //
 //		Xdsl Channel Configuration Profile For Bearer Channel 3 Upstream
-//			xDSL channel configuration profile for bearer channel 3 upstream: 	(R,-W) (optional) (2-bytes)
+//				(R,-W) (optional) (2-bytes)
 //
 type PhysicalPathTerminationPointXdslUniPart2 struct {
 	ManagedEntityDefinition
diff --git a/generated/physicalpathterminationpointxdslunipart3.go b/generated/physicalpathterminationpointxdslunipart3.go
new file mode 100644
index 0000000..454a126
--- /dev/null
+++ b/generated/physicalpathterminationpointxdslunipart3.go
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+/*
+ * NOTE: This file was generated, manual edits will be overwritten!
+ *
+ * Generated by 'goCodeGenerator.py':
+ *              https://github.com/cboling/OMCI-parser/README.md
+ */
+
+package generated
+
+import "github.com/deckarep/golang-set"
+
+// PhysicalPathTerminationPointXdslUniPart3ClassID is the 16-bit ID for the OMCI
+// Managed entity Physical path termination point xDSL UNI part 3
+const PhysicalPathTerminationPointXdslUniPart3ClassID = ClassID(427) // 0x01ab
+
+var physicalpathterminationpointxdslunipart3BME *ManagedEntityDefinition
+
+// PhysicalPathTerminationPointXdslUniPart3 (Class ID: #427 / 0x01ab)
+//	This ME represents the point in the ONU where physical paths terminate on an xDSL CO modem
+//	(xTU-C). Standards and chip sets support several forms of DSL, including VDSL2 and FAST, and the
+//	xDSL ME family is used for all of them, with specific extensions for technology variations.
+//
+//	The ONU creates or deletes an instance of this ME at the same time it creates or deletes the
+//	corresponding PPTP xDSL UNI part 1.
+//
+//	Relationships
+//		An instance of this ME is associated with each instance of a real or preprovisioned xDSL port
+//
+//	Attributes
+//		Managed Entity Id
+//			This attribute uniquely identifies each instance of this ME. This 2 byte number indicates the
+//			physical position of the UNI. The six LSBs of the first byte are the slot ID, defined in clause
+//			9.1.5. The two MSBs indicate the channel number in some of the implicitly linked MEs, and must
+//			be 0 in the PPTP itself. This reduces the possible number of physical slots to 64. The second
+//			byte is the port ID, with range 1..255. (R) (mandatory) (2 bytes)
+//
+//		Fast Line Configuration Profile
+//			This attribute points to an instance of the FAST line configuration profiles (part 1, 2, 3 and
+//			4) MEs, also to FAST vectoring line configuration extension MEs. Upon ME instantiation, the ONU
+//			sets this attribute to 0, a null pointer. (R, W) (mandatory) (2 bytes)
+//
+//		Fast Data Path Configuration Profile
+//			This attribute points to an instance of the FAST data configuration profile that defines data
+//			path parameters. Upon ME instantiation, the ONU sets this attribute to 0, a null pointer. (R, W)
+//			(optional) (2 bytes)
+//
+//		Fast Channel Configuration Profile For Bearer Channel 0 Downstream
+//			This attribute points to an instance of the FAST channel configuration profile that defines
+//			channel parameters. Upon ME instantiation, the ONU sets this attribute to 0, a null pointer.
+//			(R,-W) (optional) (2-bytes) (R,-W) (optional) (2-bytes)
+//
+//		Fast Xdsl Channel Configuration Profile For Bearer Channel 0 Upstream
+//			This attribute points to an instance of the FAST channel configuration profile that defines
+//			channel parameters. Upon ME instantiation, the ONU sets this attribute to 0, a null pointer
+//			(R,-W) (optional) (2-bytes)
+//
+type PhysicalPathTerminationPointXdslUniPart3 struct {
+	ManagedEntityDefinition
+	Attributes AttributeValueMap
+}
+
+func init() {
+	physicalpathterminationpointxdslunipart3BME = &ManagedEntityDefinition{
+		Name:    "PhysicalPathTerminationPointXdslUniPart3",
+		ClassID: 427,
+		MessageTypes: mapset.NewSetWith(
+			Get,
+			Set,
+		),
+		AllowedAttributeMask: 0xf000,
+		AttributeDefinitions: AttributeDefinitionMap{
+			0: Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read), false, false, false, 0),
+			1: Uint16Field("FastLineConfigurationProfile", UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read, Write), false, false, false, 1),
+			2: Uint16Field("FastDataPathConfigurationProfile", UnsignedIntegerAttributeType, 0x4000, 0, mapset.NewSetWith(Read, Write), false, true, false, 2),
+			3: Uint16Field("FastChannelConfigurationProfileForBearerChannel0Downstream", UnsignedIntegerAttributeType, 0x2000, 0, mapset.NewSetWith(Read, Write), false, true, false, 3),
+			4: Uint16Field("FastXdslChannelConfigurationProfileForBearerChannel0Upstream", UnsignedIntegerAttributeType, 0x1000, 0, mapset.NewSetWith(Read, Write), false, true, false, 4),
+		},
+		Access:  CreatedByOnu,
+		Support: UnknownSupport,
+	}
+}
+
+// NewPhysicalPathTerminationPointXdslUniPart3 (class ID 427) creates the basic
+// Managed Entity definition that is used to validate an ME of this type that
+// is received from or transmitted to the OMCC.
+func NewPhysicalPathTerminationPointXdslUniPart3(params ...ParamData) (*ManagedEntity, OmciErrors) {
+	return NewManagedEntity(*physicalpathterminationpointxdslunipart3BME, params...)
+}
diff --git a/generated/priorityqueue.go b/generated/priorityqueue.go
index 4022649..e58ae53 100644
--- a/generated/priorityqueue.go
+++ b/generated/priorityqueue.go
@@ -27,11 +27,11 @@
 
 // PriorityQueueClassID is the 16-bit ID for the OMCI
 // Managed entity Priority queue
-const PriorityQueueClassID ClassID = ClassID(277)
+const PriorityQueueClassID = ClassID(277) // 0x0115
 
 var priorityqueueBME *ManagedEntityDefinition
 
-// PriorityQueue (class ID #277)
+// PriorityQueue (Class ID: #277 / 0x0115)
 //	NOTE 1 - In [ITU-T G.984.4], this is called a priority queue-G.
 //
 //	This ME specifies the priority queue used by a GEM port network CTP in the upstream direction.
@@ -90,39 +90,66 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The MSB
-//			represents the direction (1: upstream, 0:-downstream). The 15 LSBs represent a queue ID. The
-//			queue ID is numbered in ascending order by the ONU itself. It is strongly encouraged that the
-//			queue ID be formulated to simplify finding related queues. One way to do this is to number the
-//			queues such that the related port attributes are in ascending order (for the downstream and
-//			upstream queues separately). The range of downstream queue ids is 0 to 0x7FFF and the range of
-//			upstream queue ids is 0x8000 to 0xFFFF. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. The MSB represents the direction
+//			(1: upstream, 0:-downstream). The 15 LSBs represent a queue ID. The queue ID is numbered in
+//			ascending order by the ONU itself. It is strongly encouraged that the queue ID be formulated to
+//			simplify finding related queues. One way to do this is to number the queues such that the
+//			related port attributes are in ascending order (for the downstream and upstream queues
+//			separately). The range of downstream queue ids is 0 to 0x7FFF and the range of upstream queue
+//			ids is 0x8000 to 0xFFFF. (R) (mandatory) (2-bytes)
 //
 //		Queue Configuration Option
-//			Queue configuration option: This attribute identifies the buffer partitioning policy. The value
-//			1 means that several queues share one buffer of maximum queue size, while the value 0 means that
-//			each queue has an individual buffer of maximum queue size. (R) (mandatory) (1-byte)
+//			This attribute identifies the buffer partitioning policy. The value 1 means that several queues
+//			share one buffer of maximum queue size, while the value 0 means that each queue has an
+//			individual buffer of maximum queue size. (R) (mandatory) (1-byte)
 //
 //		Maximum Queue Size
+//			This attribute specifies the maximum size of the queue, in bytes, scaled by the priority queue
+//			scale factor attribute of the ONU2G. (R) (mandatory) (2 bytes)
+//
 //			NOTE 2 - In this and the other similar attributes of the priority queue ME, some legacy
 //			implementations may take the queue scale factor from the GEM block length attribute of the ANI-G
 //			ME. This option is discouraged in new implementations.
 //
 //		Allocated Queue Size
-//			Allocated queue size: This attribute identifies the allocated size of this queue, in bytes,
-//			scaled by the priority queue scale factor attribute of the ONU2G. (R, W) (mandatory) (2 bytes)
+//			This attribute identifies the allocated size of this queue, in bytes, scaled by the priority
+//			queue scale factor attribute of the ONU2G. (R, W) (mandatory) (2 bytes)
 //
 //		Discard_Block Counter Reset Interval
 //			Discard-block counter reset interval: This attribute represents the interval in milliseconds at
 //			which the counter resets itself. (R,-W) (optional) (2-bytes)
 //
 //		Threshold Value For Discarded Blocks Due To Buffer Overflow
-//			Threshold value for discarded blocks due to buffer overflow: This attribute specifies the
-//			threshold for the number of bytes (scaled by the priority queue scale factor attribute of the
-//			ONU2G) discarded on this queue due to buffer overflow. Its value controls the declaration of the
-//			block loss alarm. (R, W) (optional) (2-bytes)
+//			This attribute specifies the threshold for the number of bytes (scaled by the priority queue
+//			scale factor attribute of the ONU2G) discarded on this queue due to buffer overflow. Its value
+//			controls the declaration of the block loss alarm. (R, W) (optional) (2-bytes)
 //
 //		Related Port
+//			This attribute represents the slot, port/T-CONT and priority information associated with the
+//			instance of priority queue ME. This attribute comprises 4-bytes.
+//
+//			In the upstream direction, the first 2-bytes are the ME ID of the associated T-CONT, the first
+//			byte of which is a slot number, the second byte a T-CONT number. In the downstream direction,
+//			the first byte is the slot number and the second byte is the port number of the queue's
+//			destination port.
+//
+//			The last 2-bytes represent the priority of this queue. The range of priority is 0 to 0x0FFF. The
+//			value 0 indicates the highest priority and 0x0FFF indicates the lowest priority. The priority
+//			field is meaningful if multiple priority queues are associated with a T-CONT or traffic
+//			scheduler whose scheduling discipline is strict priority.
+//
+//			(R, W) (mandatory) (4 bytes)
+//
+//			NOTE 3 - If flexible port configuration is supported, the related port attribute is meaningful
+//			only if the traffic scheduler pointer attribute value is null. Otherwise, the related port
+//			attribute is ignored.
+//
+//			NOTE 4 - The related port attribute is read-only, unless otherwise specified by the QoS
+//			configuration flexibility attribute of the ONU2-G ME. If port flexibility is supported, the
+//			second byte, the port or T-CONT number, may be changed. If priority flexibility is supported,
+//			the third and fourth bytes may be changed. The OMCI set command must contain 4-bytes to match
+//			the attribute size, but the ONU must ignore all bytes that are not specified to be flexible.
+//
 //			If flexible configuration is not supported, the ONU should reject an attempt to set the related
 //			port with a parameter error result-reason code.
 //
@@ -130,60 +157,91 @@
 //			The ONU should reject an attempt to violate these conditions with a parameter error result-
 //			reason code.
 //
+//			This attribute points to the traffic scheduler ME instance that is associated with this priority
+//			queue. This pointer is used when this priority queue is connected with a traffic scheduler. The
+//			default value is a null pointer (0). (R, W) (mandatory) (2 bytes)
+//
+//			NOTE 5 - When the QoS configuration flexibility attribute of the ONU2-G ME allows flexible
+//			assignment of the traffic scheduler, the OLT may configure the traffic scheduler pointer to
+//			refer to any traffic scheduler in the same slot.
+//
+//			If traffic scheduler flexibility is not permitted by the QoS configuration flexibility
+//			attribute, the OLT may use the traffic scheduler pointer attribute only by pointing to another
+//			traffic scheduler ME that is associated with the same T-CONT as the priority queue itself.
+//
 //		Weight
-//			Weight:	This attribute represents weight for WRR scheduling. At a given priority level, capacity
-//			is distributed to non-empty queues in proportion to their weights. In the upstream direction,
-//			this weight is meaningful if several priority queues are associated with a traffic scheduler or
+//			This attribute represents weight for WRR scheduling. At a given priority level, capacity is
+//			distributed to non-empty queues in proportion to their weights. In the upstream direction, this
+//			weight is meaningful if several priority queues are associated with a traffic scheduler or
 //			T-CONT whose policy is WRR. In the downstream direction, this weight is used by a UNI in a WRR
 //			fashion. Upon ME instantiation, the ONU sets this attribute to 1. (R,-W) (mandatory) (1-byte)
 //
 //		Back Pressure Operation
-//			Back pressure operation: This attribute enables (0) or disables (1) back pressure operation. Its
-//			default value is 0. (R,-W) (mandatory) (2-bytes)
+//			This attribute enables (0) or disables (1) back pressure operation. Its default value is 0.
+//			(R,-W) (mandatory) (2-bytes)
 //
 //		Back Pressure Time
-//			Back pressure time: This attribute specifies the duration in microseconds of the backpressure
-//			signal. It can be used as a pause time for an Ethernet UNI. Upon ME instantiation, the ONU sets
-//			this attribute to 0. (R,-W) (mandatory) (4-bytes)
+//			This attribute specifies the duration in microseconds of the backpressure signal. It can be used
+//			as a pause time for an Ethernet UNI. Upon ME instantiation, the ONU sets this attribute to 0.
+//			(R,-W) (mandatory) (4-bytes)
 //
 //		Back Pressure Occur Queue Threshold
-//			Back pressure occur queue threshold: This attribute identifies the threshold queue occupancy, in
-//			bytes, scaled by the priority queue scale factor attribute of the ONU2G, to start sending a
-//			back-pressure signal. (R, W) (mandatory) (2-bytes)
+//			This attribute identifies the threshold queue occupancy, in bytes, scaled by the priority queue
+//			scale factor attribute of the ONU2G, to start sending a back-pressure signal. (R, W) (mandatory)
+//			(2-bytes)
 //
 //		Back Pressure Clear Queue Threshold
-//			Back pressure clear queue threshold: This attribute identifies the threshold queue occupancy, in
-//			bytes, scaled by the priority queue scale factor attribute of the ONU2G, to stop sending a back-
-//			pressure signal. (R, W) (mandatory) (2-bytes)
+//			This attribute identifies the threshold queue occupancy, in bytes, scaled by the priority queue
+//			scale factor attribute of the ONU2G, to stop sending a back-pressure signal. (R, W) (mandatory)
+//			(2-bytes)
 //
 //		Packet Drop Queue Thresholds
-//			Packet drop queue thresholds: This attribute is a composite of four 2-byte values, a minimum and
-//			a maximum threshold, measured in bytes, scaled by the priority queue scale factor attribute of
-//			the ONU2-G, for green and yellow packets. The first value is the minimum green threshold, the
-//			queue occupancy below which all green packets are admitted to the queue. The second value is the
-//			maximum green threshold, the queue occupancy at or above which all green packets are discarded.
-//			The third value is the minimum yellow threshold, the queue occupancy below which all yellow
-//			packets are admitted to the queue. The fourth value is the maximum yellow threshold, the queue
-//			occupancy at or above which all yellow packets are discarded. The default is that all thresholds
-//			take the value of the maximum queue size. (R,-W) (optional) (8-bytes)
+//			This attribute is a composite of four 2-byte values, a minimum and a maximum threshold, measured
+//			in bytes, scaled by the priority queue scale factor attribute of the ONU2-G, for green and
+//			yellow packets. The first value is the minimum green threshold, the queue occupancy below which
+//			all green packets are admitted to the queue. The second value is the maximum green threshold,
+//			the queue occupancy at or above which all green packets are discarded. The third value is the
+//			minimum yellow threshold, the queue occupancy below which all yellow packets are admitted to the
+//			queue. The fourth value is the maximum yellow threshold, the queue occupancy at or above which
+//			all yellow packets are discarded. The default is that all thresholds take the value of the
+//			maximum queue size. (R,-W) (optional) (8-bytes)
 //
 //		Packet Drop Max_P
-//			Packet drop max_p: This attribute is a composite of two 1-byte values, the probability of
-//			dropping a coloured packet when the queue occupancy lies just below the maximum threshold for
-//			packets of that colour. The first value is the green packet max_p, and the second value is the
-//			yellow packet max_p. The probability, max_p, is determined by adding one to the unsigned value
-//			(0..255) of this attribute and dividing the result by 256. The default for each value is 255.
-//			(R,-W) (optional) (2-bytes)
+//			This attribute is a composite of two 1-byte values, the probability of dropping a coloured
+//			packet when the queue occupancy lies just below the maximum threshold for packets of that
+//			colour. The first value is the green packet max_p, and the second value is the yellow packet
+//			max_p. The probability, max_p, is determined by adding one to the unsigned value (0..255) of
+//			this attribute and dividing the result by 256. The default for each value is 255. (R,-W)
+//			(optional) (2-bytes)
 //
 //		Queue Drop W_Q
-//			Queue drop w_q: This attribute determines the averaging coefficient, w_q, as described in
-//			[b-Floyd]. The averaging coefficient, w_q, is equal to 2Queue_drop_w_q. For example, when queue
-//			drop_w_q has the value 9, the averaging coefficient, w_q, is 1/512-= 0.001-9. The default value
-//			is 9. (R,-W) (optional) (1-byte)
+//			This attribute determines the averaging coefficient, w_q, as described in [b-Floyd]. The
+//			averaging coefficient, w_q, is equal to 2Queue_drop_w_q. For example, when queue drop_w_q has
+//			the value 9, the averaging coefficient, w_q, is 1/512-= 0.001-9. The default value is 9. (R,-W)
+//			(optional) (1-byte)
 //
 //		Drop Precedence Colour Marking
+//			6	PCP 5P3D [IEEE 802.1ad]
+//
+//			7	DSCP AF class [IETF RFC 2597]
+//
 //			(R,-W) (optional) (1-byte)
 //
+//			This attribute specifies how drop precedence is marked on ingress packets to the priority queue.
+//			The default value is 0.
+//
+//			0	No marking (treat all packets as green)
+//
+//			1	Internal marking (from traffic descriptor ME)
+//
+//			2	DEI [IEEE 802.1ad]
+//
+//			3	PCP 8P0D [IEEE 802.1ad]
+//
+//			4	PCP 7P1D [IEEE 802.1ad]
+//
+//			5	PCP 6P2D [IEEE 802.1ad]
+//
 type PriorityQueue struct {
 	ManagedEntityDefinition
 	Attributes AttributeValueMap
diff --git a/generated/pseudowiremaintenanceprofile.go b/generated/pseudowiremaintenanceprofile.go
index 368852d..20aa1fc 100644
--- a/generated/pseudowiremaintenanceprofile.go
+++ b/generated/pseudowiremaintenanceprofile.go
@@ -27,11 +27,11 @@
 
 // PseudowireMaintenanceProfileClassID is the 16-bit ID for the OMCI
 // Managed entity Pseudowire maintenance profile
-const PseudowireMaintenanceProfileClassID ClassID = ClassID(284)
+const PseudowireMaintenanceProfileClassID = ClassID(284) // 0x011c
 
 var pseudowiremaintenanceprofileBME *ManagedEntityDefinition
 
-// PseudowireMaintenanceProfile (class ID #284)
+// PseudowireMaintenanceProfile (Class ID: #284 / 0x011c)
 //	The pseudowire maintenance profile permits the configuration of pseudowire service exception
 //	handling. It is created and deleted by the OLT.
 //
@@ -47,35 +47,66 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The value 0 is
-//			reserved. (R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. The value 0 is reserved. (R,
+//			setbycreate) (mandatory) (2-bytes)
 //
 //		Jitter Buffer Maximum Depth
-//			Jitter buffer maximum depth: This attribute specifies the desired maximum depth of the playout
-//			buffer in the PSN to the TDM direction. The value is expressed as a multiple of the 125-vs frame
-//			rate. The default value 0 selects the ONU's internal policy. (R,-W, setbycreate) (optional)
-//			(2-bytes)
+//			This attribute specifies the desired maximum depth of the playout buffer in the PSN to the TDM
+//			direction. The value is expressed as a multiple of the 125-vs frame rate. The default value 0
+//			selects the ONU's internal policy. (R,-W, setbycreate) (optional) (2-bytes)
 //
 //		Jitter Buffer Desired Depth
-//			Jitter buffer desired depth: This attribute specifies the desired nominal fill depth of the
-//			playout buffer in the PSN to the TDM direction. The value is expressed as a multiple of the
-//			125-vs frame rate. The default value 0 selects the ONU's internal policy. (R,-W, setbycreate)
-//			(optional) (2-bytes)
+//			This attribute specifies the desired nominal fill depth of the playout buffer in the PSN to the
+//			TDM direction. The value is expressed as a multiple of the 125-vs frame rate. The default value
+//			0 selects the ONU's internal policy. (R,-W, setbycreate) (optional) (2-bytes)
 //
 //		Fill Policy
+//			This attribute defines the payload bit pattern to be applied towards the TDM service if no
+//			payload packet is available to play out. The default value 0 specifies that the ONU apply its
+//			internal policy.
+//
+//			0	ONU default, vendor-specific (recommended: AIS for unstructured service, all 1s for structured
+//			service)
+//
+//			1	Play out AIS according to the service definition (for example, DS3 AIS)
+//
+//			2	Play out all 1s
+//
+//			3	Play out all 0s
+//
+//			4	Repeat the previous data
+//
+//			5	Play out DS1 idle (Appendix C of [b-ATIS-0600403])
+//
+//			6..15	Reserved for future standardization
+//
+//			16..255	Vendor-specific, not to be standardized
+//
 //			(R,-W, setbycreate) (optional) (1-byte)
 //
+//			Four pairs of alarm-related policy attributes, defined in the following, share common behaviour.
+//
+//			The alarm declaration policy attribute defines the anomaly rate that causes the corresponding
+//			alarm to be declared. It is an integer percentage between 1..100. If this density of anomalies
+//			occurs during the alarm onset soak interval, the alarm is declared. The default value 0 selects
+//			the ONU's internal policy.
+//
+//			The alarm clear policy attribute defines the anomaly rate that causes the corresponding alarm to
+//			be cleared. It is an integer percentage between 0..99. If no more than this density of anomalies
+//			occurs during the alarm clear soak interval, the alarm is cleared. The default value 255 selects
+//			the ONU's internal policy.
+//
 //		Misconnected Packets Declaration Policy
-//			Misconnected packets declaration policy: (R,-W, setbycreate) (optional) (1-byte)
+//			(R,-W, setbycreate) (optional) (1-byte)
 //
 //		Misconnected Packets Clear Policy
-//			Misconnected packets clear policy: (R,-W, setbycreate) (optional) (1-byte)
+//			(R,-W, setbycreate) (optional) (1-byte)
 //
 //		Loss Of Packets Declaration Policy
-//			Loss of packets declaration policy: (R,-W, setbycreate) (optional) (1-byte)
+//			(R,-W, setbycreate) (optional) (1-byte)
 //
 //		Loss Of Packets Clear Policy
-//			Loss of packets clear policy: (R,-W, setbycreate) (optional) (1-byte)
+//			(R,-W, setbycreate) (optional) (1-byte)
 //
 //		Buffer Overrun_Underrun Declaration Policy
 //			Buffer overrun/underrun declaration policy: (R,-W, setbycreate) (optional) (1-byte)
@@ -84,10 +115,10 @@
 //			Buffer overrun/underrun clear policy: (R,-W, setbycreate) (optional) (1-byte)
 //
 //		Malformed Packets Declaration Policy
-//			Malformed packets declaration policy: (R,-W, setbycreate) (optional) (1-byte)
+//			(R,-W, setbycreate) (optional) (1-byte)
 //
 //		Malformed Packets Clear Policy
-//			Malformed packets clear policy: (R,-W, setbycreate) (optional) (1-byte)
+//			(R,-W, setbycreate) (optional) (1-byte)
 //
 //		R_Bit Transmit Set Policy
 //			R-bit transmit set policy: This attribute defines the number of consecutive lost packets that
@@ -102,17 +133,36 @@
 //			setbycreate) (optional) (1-byte)
 //
 //		R_Bit Receive Policy
+//			R-bit receive policy: This attribute defines the action towards the N-*-64 TDM interface when
+//			remote failure is indicated on packets received from the PSN (either Rbit set or M-=-0b10 while
+//			the L bit is cleared).
+//
+//			0	Do nothing (recommended to be the default)
+//
+//			1	Play out service-specific RAI/REI/RDI code
+//
+//			2	Send channel idle signalling and idle channel payload to all DS0s comprising the service
+//
 //			(R,-W, setbycreate) (optional) (1-byte)
 //
 //		L Bit Receive Policy
+//			This attribute defines the action towards the TDM interface when farend TDM failure is indicated
+//			on packets received from the PSN (L bit set).
+//
+//			0	Play out service-specific AIS (recommended to be the default)
+//
+//			1	Repeat last received packet
+//
+//			2	Send channel idle signalling and idle channel payload to all DS0s comprising the service
+//
 //			(R,-W, setbycreate) (optional) (1-byte)
 //
 //		Ses Threshold
-//			SES threshold: Number of lost, malformed or otherwise unusable packets expected in the PSN to
-//			the TDM direction within a 1-s interval that causes an SES to be counted. Stray packets do not
-//			count towards an SES, nor do packets whose L bit is set at the far end. The value 0 specifies
-//			that the ONU uses its internal default, which is not necessarily the same as the recommended
-//			default value 3. (R, W, set-by-create) (optional) (2 bytes)
+//			Number of lost, malformed or otherwise unusable packets expected in the PSN to the TDM direction
+//			within a 1-s interval that causes an SES to be counted. Stray packets do not count towards an
+//			SES, nor do packets whose L bit is set at the far end. The value 0 specifies that the ONU uses
+//			its internal default, which is not necessarily the same as the recommended default value 3. (R,
+//			W, set-by-create) (optional) (2 bytes)
 //
 type PseudowireMaintenanceProfile struct {
 	ManagedEntityDefinition
diff --git a/generated/pseudowireperformancemonitoringhistorydata.go b/generated/pseudowireperformancemonitoringhistorydata.go
index 23e4114..e570ba2 100644
--- a/generated/pseudowireperformancemonitoringhistorydata.go
+++ b/generated/pseudowireperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // PseudowirePerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity Pseudowire performance monitoring history data
-const PseudowirePerformanceMonitoringHistoryDataClassID ClassID = ClassID(285)
+const PseudowirePerformanceMonitoringHistoryDataClassID = ClassID(285) // 0x011d
 
 var pseudowireperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// PseudowirePerformanceMonitoringHistoryData (class ID #285)
+// PseudowirePerformanceMonitoringHistoryData (Class ID: #285 / 0x011d)
 //	This ME collects PM for a pseudowire TP. Most of the attributes monitor packets received from
 //	the PSN, and may therefore be considered egress PM. For the most part, ingress PM is collected
 //	at the CES PPTP ME.
@@ -49,42 +49,39 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the pseudowire TP. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the pseudowire TP. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 and 2 MEs
 //			that contains PM threshold values. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Received Packets
-//			Received packets: This attribute counts the total number of packets, both payload and
-//			signalling, received in the PSN to the TDM direction. (R) (mandatory) (4-bytes)
+//			This attribute counts the total number of packets, both payload and signalling, received in the
+//			PSN to the TDM direction. (R) (mandatory) (4-bytes)
 //
 //		Transmitted Packets
-//			Transmitted packets: This attribute counts the total number of packets, both payload and
-//			signalling, transmitted in the TDM to the PSN direction. The count includes packets whose L bit
-//			is set and which may therefore not contain a payload. (R) (mandatory) (4-bytes)
+//			This attribute counts the total number of packets, both payload and signalling, transmitted in
+//			the TDM to the PSN direction. The count includes packets whose L bit is set and which may
+//			therefore not contain a payload. (R) (mandatory) (4-bytes)
 //
 //		Missing Packets
-//			Missing packets: This attribute counts the number of lost packets, as indicated by gaps in the
-//			control word numbering sequence. Both payload and signalling packets, if any, contribute to this
-//			count. (R) (mandatory) (4-bytes)
+//			This attribute counts the number of lost packets, as indicated by gaps in the control word
+//			numbering sequence. Both payload and signalling packets, if any, contribute to this count. (R)
+//			(mandatory) (4-bytes)
 //
 //		Misordered Packets, Usable
-//			Misordered packets, usable: This attribute counts the number of packets received out of order,
-//			but which were able to be successfully re-ordered and played out. Both payload and signalling
-//			packets, if any, contribute to this count. (R) (mandatory) (4-bytes)
+//			This attribute counts the number of packets received out of order, but which were able to be
+//			successfully re-ordered and played out. Both payload and signalling packets, if any, contribute
+//			to this count. (R) (mandatory) (4-bytes)
 //
 //		Misordered Packets Dropped
-//			Misordered packets dropped: This attribute counts the number of packets received out of sequence
-//			that were discarded, either because the ONU did not support reordering or because it was too
-//			late to reorder them. Both payload and signalling packets, if any, contribute to this count. (R)
-//			(mandatory) (4-bytes)
+//			This attribute counts the number of packets received out of sequence that were discarded, either
+//			because the ONU did not support reordering or because it was too late to reorder them. Both
+//			payload and signalling packets, if any, contribute to this count. (R) (mandatory) (4-bytes)
 //
 //		Playout Buffer Underruns_Overruns
 //			Playout buffer underruns/overruns: This attribute counts the number of packets that were
@@ -92,20 +89,20 @@
 //			signalling packets, if any, contribute to this count. (R) (mandatory) (4-bytes)
 //
 //		Malformed Packets
-//			Malformed packets: This attribute counts the number of malformed packets, e.g., because the
-//			packet length was not as expected or because of an unexpected RTP payload type. Both payload and
-//			signalling packets, if any, contribute to this count. (R) (mandatory) (4-bytes)
+//			This attribute counts the number of malformed packets, e.g., because the packet length was not
+//			as expected or because of an unexpected RTP payload type. Both payload and signalling packets,
+//			if any, contribute to this count. (R) (mandatory) (4-bytes)
 //
 //		Stray Packets
-//			Stray packets: This attribute counts the number of packets whose ECID or RTP SSRC failed to
-//			match the expected value, or which are otherwise known to have been misdelivered. Stray packets
-//			are discarded without affecting any of the other PM counters. Both payload and signalling
-//			packets, if any, contribute to this count. (R) (mandatory) (4-bytes)
+//			This attribute counts the number of packets whose ECID or RTP SSRC failed to match the expected
+//			value, or which are otherwise known to have been misdelivered. Stray packets are discarded
+//			without affecting any of the other PM counters. Both payload and signalling packets, if any,
+//			contribute to this count. (R) (mandatory) (4-bytes)
 //
 //		Remote Packet Loss
-//			Remote packet loss: This attribute counts received packets whose R bit is set, indicating the
-//			loss of packets at the far end. Both payload and signalling packets, if any, contribute to this
-//			count. (R) (mandatory) (4-bytes)
+//			This attribute counts received packets whose R bit is set, indicating the loss of packets at the
+//			far end. Both payload and signalling packets, if any, contribute to this count. (R) (mandatory)
+//			(4-bytes)
 //
 //		Tdm L_Bit Packets Transmitted
 //			TDM L-bit packets transmitted: This attribute counts the number of packets transmitted with the
@@ -113,17 +110,17 @@
 //			contribute to this count. (R) (mandatory) (4-bytes)
 //
 //		Es
-//			ES:	This attribute counts errored seconds. Any discarded, lost, malformed or unusable packet
+//			This attribute counts errored seconds. Any discarded, lost, malformed or unusable packet
 //			received from the PSN during a given second causes this counter to increment. Both payload and
 //			signalling packets, if any, contribute to this count. (R) (mandatory) (4-bytes)
 //
 //		Ses
-//			SES:	This attribute counts severely errored seconds. The criterion for an SES may be configured
+//			This attribute counts severely errored seconds. The criterion for an SES may be configured
 //			through the pseudowire maintenance profile ME. Both payload and signalling packets, if any,
 //			contribute to this count. (R) (mandatory) (4-bytes)
 //
 //		Uas
-//			UAS:	This attribute counts unavailable seconds. An unavailable second begins at the onset of 10
+//			This attribute counts unavailable seconds. An unavailable second begins at the onset of 10
 //			consecutive SES and ends at the onset of 10 consecutive seconds that are not severely errored. A
 //			service is unavailable if either its payload or its signalling, if any, are unavailable. During
 //			unavailable time, only UAS should be counted; other anomalies should not be counted. (R)
diff --git a/generated/pseudowireterminationpoint.go b/generated/pseudowireterminationpoint.go
index 54f30ec..31e0654 100644
--- a/generated/pseudowireterminationpoint.go
+++ b/generated/pseudowireterminationpoint.go
@@ -27,11 +27,11 @@
 
 // PseudowireTerminationPointClassID is the 16-bit ID for the OMCI
 // Managed entity Pseudowire termination point
-const PseudowireTerminationPointClassID ClassID = ClassID(282)
+const PseudowireTerminationPointClassID = ClassID(282) // 0x011a
 
 var pseudowireterminationpointBME *ManagedEntityDefinition
 
-// PseudowireTerminationPoint (class ID #282)
+// PseudowireTerminationPoint (Class ID: #282 / 0x011a)
 //	The pseudowire TP supports packetized (rather than TDM) transport of TDM services, transported
 //	either directly over Ethernet, over UDP/IP or over MPLS. Instances of this ME are created and
 //	deleted by the OLT.
@@ -41,22 +41,45 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Underlying Transport
+//			2	MPLS
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
+//			Underlying transport:
+//
+//			0	Ethernet, MEF 8
+//
+//			1	UDP/IP
+//
 //		Service Type
+//			This attribute specifies the basic service type, either a transparent bit pipe or an
+//			encapsulation that recognizes the underlying structure of the payload.
+//
+//			0	Basic unstructured (also known as structure agnostic)
+//
+//			1	Octet-aligned unstructured, structure agnostic. Applicable only to DS1, a mode in which each
+//			frame of 193 bits is encapsulated in 25 bytes with 7 padding bits.
+//
+//			2	Structured (structure-locked)
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Signalling
+//			1	CAS, to be carried in the same packet stream as the payload
+//
+//			2	CAS, to be carried in a separate signalling channel
+//
 //			(R,-W, setbycreate) (mandatory for structured service type) (1-byte)
 //
+//				0	No signalling visible at this layer
+//
 //		Tdm Uni Pointer
-//			TDM UNI pointer: If service type-= structured, this attribute points to a logical N-* 64-kbit/s
-//			subport CTP. Otherwise, this attribute points to a PPTP CES UNI. (R,-W, setbycreate) (mandatory)
-//			(2-bytes)
+//			If service type-= structured, this attribute points to a logical N-* 64-kbit/s subport CTP.
+//			Otherwise, this attribute points to a PPTP CES UNI. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		North_Side Pointer
 //			North-side pointer: When the pseudowire service is transported via IP, as indicated by the
@@ -70,36 +93,91 @@
 //			A null pointer is appropriate if the pseudowire is not transported via IP. (R,-W, setbycreate)
 //			(mandatory for IP transport) (2-bytes)
 //
+//			Far-end IP info: When the pseudowire service is transported via IP, this attribute points to a
+//			large string ME that contains the URI of the far-end TP, e.g.,
+//
+//			udp://192.168.100.221:5000
+//
+//			udp://pwe3srvr.int.example.net:2222
+//
 //		Payload Size
+//			Number of payload bytes per packet. Valid only if service type-= basic unstructured or octet-
+//			aligned unstructured. Valid choices depend on the TDM service, but must include the following.
+//			Other choices are at the vendor's discretion.
+//
+//			DS1	192
+//
+//			DS1	200, required only if an octet-aligned unstructured service is supported
+//
+//			E1	256
+//
+//			DS3	1024
+//
+//			E3	1024
+//
 //			(R,-W, setbycreate) (mandatory for unstructured service) (2-bytes)
 //
 //		Payload Encapsulation Delay
+//			Number of 125-us frames to be encapsulated in each pseudowire packet. Valid only if service
+//			type-= structured. The minimum set of choices for various TDM services is listed in the
+//			following table, and is affected by the possible presence of in-band signalling. Other choices
+//			are at the vendor's discretion.
+//
 //			(R,-W, setbycreate) (mandatory for structured service) (1-byte)
 //
 //		Timing Mode
 //			(R,-W) (mandatory) (1-byte)
 //
+//			This attribute selects the timing mode of the TDM service. If RTP is used, this attribute must
+//			be set to be consistent with the value of the RTP timestamp mode attribute in the RTP pseudowire
+//			parameters ME, or its equivalent, at the far end.
+//
+//			0	Network timing (default)
+//
+//			1	Differential timing
+//
+//			2	Adaptive timing
+//
+//			3	Loop timing: local TDM transmit clock derived from local TDM receive stream
+//
 //		Transmit Circuit Id
+//			This attribute is a pair of emulated circuit ID (ECID) values that the ONU transmits in the
+//			direction from the TDM termination towards the packet-switched network (PSN). MEF 8 ECIDs lie in
+//			the range 1..1048575 (220-- 1). To allow for the possibility of other transport (L2TP) in the
+//			future, each ECID is allocated 4-bytes.
+//
+//			The first value is used for the payload ECID; the second is used for the optional separate
+//			signalling ECID. The first ECID is required for all MEF 8 pseudowires; the second is required
+//			only if signalling is to be carried in a distinct channel. If signalling is not present, or is
+//			carried in the same channel as the payload, the second ECID should be set to 0.
+//
 //			(R,-W) (mandatory for MEF 8 transport) (8-bytes)
 //
 //		Expected Circuit Id
+//			This attribute is a pair of ECID values that the ONU can expect in the direction from the PSN
+//			towards the TDM termination. Checking ECIDs may be a way to detect circuit misconnection. MEF 8
+//			ECIDs lie in the range 1..1048575 (220-- 1). To allow for the possibility of other transport
+//			(L2TP) in the future, each ECID is allocated 4-bytes.
+//
+//			The first value is used for the payload ECID; the second is used for the optional separate
+//			signalling ECID. In both cases, the default value 0 indicates that no ECID checking is expected.
+//
 //			(R,-W) (optional for MEF 8 transport) (8-bytes)
 //
 //		Received Circuit Id
-//			Received circuit ID: This attribute indicates the actual ECID(s) received on the payload and
-//			signalling channels, respectively. It may be used for diagnostic purposes. (R) (optional for MEF
-//			8 transport) (8-bytes)
+//			This attribute indicates the actual ECID(s) received on the payload and signalling channels,
+//			respectively. It may be used for diagnostic purposes. (R) (optional for MEF 8 transport)
+//			(8-bytes)
 //
 //		Exception Policy
-//			Exception policy: This attribute points to an instance of the pseudowire maintenance profile ME.
-//			If the pointer has its default value 0, the ONU's internal defaults apply. (R,-W) (optional)
-//			(2-bytes)
+//			This attribute points to an instance of the pseudowire maintenance profile ME. If the pointer
+//			has its default value 0, the ONU's internal defaults apply. (R,-W) (optional) (2-bytes)
 //
 //		Arc
-//			ARC:	See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Arc Interval
-//			ARC interval: See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 type PseudowireTerminationPoint struct {
 	ManagedEntityDefinition
diff --git a/generated/pwatmconfigurationdata.go b/generated/pwatmconfigurationdata.go
index fb53f29..0cd5ec4 100644
--- a/generated/pwatmconfigurationdata.go
+++ b/generated/pwatmconfigurationdata.go
@@ -27,11 +27,11 @@
 
 // PwAtmConfigurationDataClassID is the 16-bit ID for the OMCI
 // Managed entity PW ATM configuration data
-const PwAtmConfigurationDataClassID ClassID = ClassID(337)
+const PwAtmConfigurationDataClassID = ClassID(337) // 0x0151
 
 var pwatmconfigurationdataBME *ManagedEntityDefinition
 
-// PwAtmConfigurationData (class ID #337)
+// PwAtmConfigurationData (Class ID: #337 / 0x0151)
 //	This ME contains generic configuration data for an ATM pseudowire. Definitions of attributes are
 //	from PW-ATM-MIB [IETF RFC 5605]. Instances of this ME are created and deleted by the OLT.
 //
@@ -42,20 +42,26 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R,
-//			setbycreate)-(mandatory) (2 bytes)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate)-(mandatory) (2
+//			bytes)
 //
 //		Tp Type
+//			This attribute specifies the type of the underlying transport layer. (R, W, setbycreate)
+//			(mandatory) (1 byte)
+//
+//			0	MPLS pseudowire termination point
+//
+//			1	Ethernet flow termination point
+//
 //			2	TCP/UDP config data
 //
 //		Transport Tp Pointer
-//			Transport TP pointer: This attribute points to an associated instance of the transport layer TP,
-//			whose type is specified by the TP type attribute. (R, W, setbycreate) (mandatory) (2 bytes)
+//			This attribute points to an associated instance of the transport layer TP, whose type is
+//			specified by the TP type attribute. (R, W, setbycreate) (mandatory) (2 bytes)
 //
 //		Pptp Atm Uni Pointer
-//			PPTP ATM UNI pointer: This attribute points to an associated instance of the ITU-T G.983.2 PPTP
-//			ATM UNI. Refer to [ITUT G.983.2] for the definition of the target ME. (R, W, setbycreate)
-//			(mandatory) (2 bytes)
+//			This attribute points to an associated instance of the ITU-T G.983.2 PPTP ATM UNI. Refer to
+//			[ITUT G.983.2] for the definition of the target ME. (R, W, setbycreate) (mandatory) (2 bytes)
 //
 //		Max C Ell C Oncatenation
 //			Max cell concatenation: This attribute specifies the maximum number of ATM cells that can be
@@ -69,6 +75,14 @@
 //			default. (R, W, set-by-create) (optional) (2 bytes)
 //
 //		Atm Cell Loss Priority Clp Qos Mapping
+//			ATM cell loss priority (CLP) QoS mapping: This attribute specifies whether the CLP bits should
+//			be considered when setting the value in the QoS fields of the encapsulating protocol (e.g., TC
+//			fields of the MPLS label stack).
+//
+//			1	ATM CLP bits mapping to QoS fields of the encapsulating protocol
+//
+//			2	Not applicable
+//
 //			The value 0 specifies that the ONU uses its internal default. (R, W, setbycreate) (optional) (1
 //			byte)
 //
@@ -76,9 +90,139 @@
 //			The value 0 specifies that the ONU uses its internal default. (R, W, setbycreate) (optional) (1
 //			byte)
 //
+//			This attribute specifies whether a packet is transmitted in the upstream direction based on
+//			timeout expiration for collecting cells. The actual handling of the timeout is implementation
+//			specific; as such, this attribute may be changed at any time with proper consideration of the
+//			traffic disruption effect.
+//
+//			1	Disabled. The ONU does not generate packets based on timeout cells.
+//
+//			2	Enabled. The ONU generates packets based on timeout cells.
+//
 //		Pw Atm Mapping Table
+//			12	ATM one-to-one VCC cell mode
+//
+//			13	ATM one-to-one VPC cell mode
+//
+//			14	ATM AAL5 PDU VCC transport
+//
+//			Each entry contains:
+//
+//			Entry number: (1-byte), the index of this row. A set operation with all fields zero has the
+//			effect of clearing the table. A set operation with a non-zero entry number and all other fields
+//			zero, has the effect of deleting one row.
+//
+//			Upstream VPI: (2 bytes)
+//
+//			The VPI value of this ATM PW at the UNI. When pseudowire type-= ATM transparent cell transport
+//			(3), this field is ignored.
+//
+//			Upstream VCI: (2 bytes)
+//
+//			The VCI value of this ATM PW at the UNI. When pseudowire type-= ATM transparent cell transport
+//			(3), or in virtual path (VP) cases, this field is ignored.
+//
+//			Upstream traffic descriptor profile pointer: (2 bytes)
+//
+//			A pointer to an instance of an ITU-T G.983.2 traffic descriptor profile ME that contains the
+//			traffic parameters used for the ATM upstream traffic. Refer to clause 7.5.2 of [ITUT-G.983.2]
+//			for the definition of this class of MEs. A null pointer indicates BE.
+//
+//			Upstream mapped VPI: (2 bytes)
+//
+//			The VPI value of the upstream MPLS ATM PW. This field is valid when the pseudowire type is as
+//			follows.
+//
+//			9	ATM n-to-one VCC cell transport
+//
+//			10	ATM n-to-one VPC cell transport
+//
+//			12	ATM one-to-one VCC cell mode
+//
+//			13	ATM one-to-one VPC cell mode
+//
+//			This field is not used for other pseudowire types.
+//
+//			Upstream mapped VCI: (2 bytes)
+//
+//			The VCI value of the upstream MPLS ATM PW. This field is valid when the pseudowire type is as
+//			follows.
+//
+//			9	ATM n-to-one VCC cell transport
+//
+//			10	ATM n-to-one VPC cell transport
+//
+//			12	ATM one-to-one VCC cell mode
+//
+//			13	ATM one-to-one VPC cell mode
+//
+//			This field is not used for other pseudowire types.
+//
+//			Downstream VPI: (2 bytes)
+//
+//			The downstream VPI value of this MPLS ATM PW. When pseudowire type-= ATM transparent cell
+//			transport (3), this field is ignored.
+//
+//			Downstream VCI: (2 bytes)
+//
+//			The downstream VCI value of this MPLS ATM PW. When pseudowire type-= ATM transparent cell
+//			transport (3) or in the VP case, this field is ignored.
+//
+//			Downstream traffic descriptor profile pointer: (2 bytes)
+//
+//			A pointer to an instance of an ITU-T G.983.2 traffic descriptor profile ME that contains the
+//			traffic parameters used for the ATM downstream traffic. Refer to clause 7.5.2 of [ITUT-G.983.2]
+//			for definition of this class of MEs. A null pointer indicates BE.
+//
+//			Downstream mapped VPI: (2 bytes)
+//
+//			The VPI value of this ATM PW at the UNI. This field is valid when the pseudowire type is as
+//			follows.
+//
+//			9	ATM n-to-one VCC cell transport
+//
+//			10	ATM n-to-one VPC cell transport
+//
+//			12	ATM one-to-one VCC cell mode
+//
+//			13	ATM one-to-one VPC cell mode
+//
+//			This field is not used for other pseudowire types.
+//
+//			Downstream mapped VCI: (2 bytes)
+//
+//			The VCI value of this ATM PW at the UNI. This field is valid when the pseudowire type is as
+//			follows.
+//
+//			9	ATM n-to-one VCC cell transport
+//
+//			10	ATM n-to-one VPC cell transport
+//
+//			12	ATM one-to-one VCC cell mode
+//
+//			13	ATM one-to-one VPC cell mode
+//
+//			This field is not used for other pseudowire types.
+//
 //			(R,-W) (mandatory) (21N bytes, where N is the number of entries in the list)
 //
+//			This attribute lists ATM VPI/VCI mapping entries in both the upstream and downstream directions.
+//			In the upstream direction, ATM cells that match no entry's upstream VPI (and conditionally VCI)
+//			values are discarded; conversely in the downstream direction. Upon ME instantiation, the ONU
+//			sets this attribute to an empty table, which discards all cells in both directions.
+//
+//			The table can contain up to N entries when the pseudowire type is equal to one of the following:
+//
+//			9 	ATM n-to-one VCC cell transport
+//
+//			10	ATM n-to-one VPC cell transport
+//
+//			The table contains only one entry when the pseudowire type is equal to one of the following.
+//
+//			2 	ATM AAL5 SDU VCC transport
+//
+//			3 	ATM transparent cell transport
+//
 type PwAtmConfigurationData struct {
 	ManagedEntityDefinition
 	Attributes AttributeValueMap
diff --git a/generated/pwatmperformancemonitoringhistorydata.go b/generated/pwatmperformancemonitoringhistorydata.go
index c03552a..5e18218 100644
--- a/generated/pwatmperformancemonitoringhistorydata.go
+++ b/generated/pwatmperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // PwAtmPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity PW ATM performance monitoring history data
-const PwAtmPerformanceMonitoringHistoryDataClassID ClassID = ClassID(338)
+const PwAtmPerformanceMonitoringHistoryDataClassID = ClassID(338) // 0x0152
 
 var pwatmperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// PwAtmPerformanceMonitoringHistoryData (class ID #338)
+// PwAtmPerformanceMonitoringHistoryData (Class ID: #338 / 0x0152)
 //	This ME collects PM data associated with an ATM pseudowire. Instances of this ME are created and
 //	deleted by the OLT.
 //
@@ -42,13 +42,12 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to the instance of the PW ATM configuration data ME.
-//			(R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to the instance of the PW ATM configuration data ME. (R, setbycreate)
+//			(mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -56,31 +55,30 @@
 //			data 2 ME is optional. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Downstream Missing Packets Counter
-//			Downstream missing packets counter: This attribute counts missing packets, as detected via
-//			control word sequence number gaps. (R) (mandatory) (4-bytes)
+//			This attribute counts missing packets, as detected via control word sequence number gaps. (R)
+//			(mandatory) (4-bytes)
 //
 //		Downstream Reordered Packets Counter
-//			Downstream reordered packets counter: This attribute counts packets detected out of sequence via
-//			the control word sequence number, but successfully reordered. Some implementations may not
-//			support this feature. (R) (optional) (4-bytes)
-//
-//		Downstream Misordered Packets Counter
-//			Downstream misordered packets counter: This attribute counts packets detected out of order via
-//			the control word sequence numbers. (R) (mandatory) (4-bytes)
-//
-//		Upstream Timeout Packets Counter
-//			Upstream timeout packets counter: This attribute counts packets transmitted due to timeout
-//			expiration while attempting to collect cells. (R) (mandatory) (4-bytes)
-//
-//		Upstream Transmitted Cells Counter
-//			Upstream transmitted cells counter: This attribute counts transmitted cells. (R) (mandatory)
+//			This attribute counts packets detected out of sequence via the control word sequence number, but
+//			successfully reordered. Some implementations may not support this feature. (R) (optional)
 //			(4-bytes)
 //
+//		Downstream Misordered Packets Counter
+//			This attribute counts packets detected out of order via the control word sequence numbers. (R)
+//			(mandatory) (4-bytes)
+//
+//		Upstream Timeout Packets Counter
+//			This attribute counts packets transmitted due to timeout expiration while attempting to collect
+//			cells. (R) (mandatory) (4-bytes)
+//
+//		Upstream Transmitted Cells Counter
+//			This attribute counts transmitted cells. (R) (mandatory) (4-bytes)
+//
 //		Upstream Dropped Cells Counter
-//			Upstream dropped cells counter: This attribute counts dropped cells. (R) (mandatory) (4-bytes)
+//			This attribute counts dropped cells. (R) (mandatory) (4-bytes)
 //
 //		Upstream Received Cells Counter
-//			Upstream received cells counter: This attribute counts received cells. (R) (mandatory) (4-bytes)
+//			This attribute counts received cells. (R) (mandatory) (4-bytes)
 //
 type PwAtmPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/pwethernetconfigurationdata.go b/generated/pwethernetconfigurationdata.go
index 11a6f4b..97e5f97 100644
--- a/generated/pwethernetconfigurationdata.go
+++ b/generated/pwethernetconfigurationdata.go
@@ -27,11 +27,11 @@
 
 // PwEthernetConfigurationDataClassID is the 16-bit ID for the OMCI
 // Managed entity PW Ethernet configuration data
-const PwEthernetConfigurationDataClassID ClassID = ClassID(339)
+const PwEthernetConfigurationDataClassID = ClassID(339) // 0x0153
 
 var pwethernetconfigurationdataBME *ManagedEntityDefinition
 
-// PwEthernetConfigurationData (class ID #339)
+// PwEthernetConfigurationData (Class ID: #339 / 0x0153)
 //	This ME contains the Ethernet pseudowire configuration data. Instances of this ME are created
 //	and deleted by the OLT.
 //
@@ -41,19 +41,36 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R,
-//			setbycreate)-(mandatory) (2 bytes)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate)-(mandatory) (2
+//			bytes)
 //
 //		Mpls Pseudowire Tp Pointer
-//			MPLS pseudowire TP pointer: This attribute points to an instance of the MPLS pseudowire TP ME
-//			associated with this ME. (R, W, setbycreate) (mandatory) (2 bytes)
+//			This attribute points to an instance of the MPLS pseudowire TP ME associated with this ME. (R,
+//			W, setbycreate) (mandatory) (2 bytes)
 //
 //		Tp Type
+//			This attribute identifies the type of UNI associated with this Ethernet PW. Valid values are as
+//			follows.
+//
+//			1	Physical path termination point Ethernet UNI
+//
+//			3	IEEE 802.1p mapper service profile
+//
+//			7	Physical path termination point xDSL UNI part 1
+//
+//			11	Virtual Ethernet interface point
+//
+//			12	Physical path termination point MoCA UNI
+//
+//			13	MAC bridge port configuration data
+//
+//			Other values are reserved
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Uni Pointer
-//			UNI pointer: This attribute points to the associated instance of a UNI-side ME. The type of UNI
-//			is determined by the TP type attribute. (R, W, setbycreate) (mandatory) (2 bytes)
+//			This attribute points to the associated instance of a UNI-side ME. The type of UNI is determined
+//			by the TP type attribute. (R, W, setbycreate) (mandatory) (2 bytes)
 //
 type PwEthernetConfigurationData struct {
 	ManagedEntityDefinition
diff --git a/generated/radiusperformancemonitoringhistorydata.go b/generated/radiusperformancemonitoringhistorydata.go
index 0fb3e07..2dd144a 100644
--- a/generated/radiusperformancemonitoringhistorydata.go
+++ b/generated/radiusperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // RadiusPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity Radius performance monitoring history data
-const RadiusPerformanceMonitoringHistoryDataClassID ClassID = ClassID(293)
+const RadiusPerformanceMonitoringHistoryDataClassID = ClassID(293) // 0x0125
 
 var radiusperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// RadiusPerformanceMonitoringHistoryData (class ID #293)
+// RadiusPerformanceMonitoringHistoryData (Class ID: #293 / 0x0125)
 //	This ME collects performance statistics on an ONU's radius client, particularly as related to
 //	its IEEE-802.1X operation.
 //
@@ -44,13 +44,12 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID (namely 0), this ME is implicitly linked to an instance of a dot1X configuration
-//			profile. (R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID (namely 0),
+//			this ME is implicitly linked to an instance of a dot1X configuration profile. (R, setbycreate)
+//			(mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -78,8 +77,7 @@
 //			(R) (mandatory) (4-bytes)
 //
 //		Invalid Radius Packets Received
-//			Invalid radius packets received: This attribute counts received invalid radius messages. (R)
-//			(mandatory) (4-bytes)
+//			This attribute counts received invalid radius messages. (R) (mandatory) (4-bytes)
 //
 type RadiusPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/reani-g.go b/generated/reani-g.go
index 6b696d6..fcbb5c2 100644
--- a/generated/reani-g.go
+++ b/generated/reani-g.go
@@ -27,11 +27,11 @@
 
 // ReAniGClassID is the 16-bit ID for the OMCI
 // Managed entity RE ANI-G
-const ReAniGClassID ClassID = ClassID(313)
+const ReAniGClassID = ClassID(313) // 0x0139
 
 var reanigBME *ManagedEntityDefinition
 
-// ReAniG (class ID #313)
+// ReAniG (Class ID: #313 / 0x0139)
 //	This ME organizes data associated with each R'/S' physical interface of an RE if the RE supports
 //	OEO regeneration in either direction. The management ONU automatically creates one instance of
 //	this ME for each R'/S' physical port (uni- or bidirectional) as follows.
@@ -68,10 +68,17 @@
 //
 //	Attributes
 //		Managed Entity Id
+//			This attribute uniquely identifies each instance of this ME. Its value indicates the physical
+//			position of the R'/S' interface. The first byte is the slot ID (defined in clause 9.1.5). The
+//			second byte is the port ID. (R) (mandatory) (2-bytes)
+//
 //			NOTE 1 - This ME ID may be identical to that of an RE downstream amplifier if it shares the same
 //			physical slot and port.
 //
 //		Administrative State
+//			This attribute locks (1) and unlocks (0) the functions performed by this ME. Administrative
+//			state is further described in clause A.1.6. (R,-W) (mandatory) (1-byte)
+//
 //			NOTE 2 - When an RE supports multiple PONs, or protected access to a single PON, its primary
 //			ANI-G cannot be completely shut down, due to a loss of the management communications capability.
 //			Complete blocking of service and removal of power may nevertheless be appropriate for secondary
@@ -79,78 +86,88 @@
 //			primary or secondary.
 //
 //		Operational State
-//			Operational state: This attribute indicates whether the ME is capable of performing its
-//			function. Valid values are enabled (0) and disabled (1). (R) (optional) (1-byte)
+//			This attribute indicates whether the ME is capable of performing its function. Valid values are
+//			enabled (0) and disabled (1). (R) (optional) (1-byte)
 //
 //		Arc
-//			ARC:	See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Arc Interval
-//			ARC interval: See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Optical Signal Level
-//			Optical signal level: This attribute reports the current measurement of total downstream optical
-//			power. Its value is a 2s complement integer referred to 1-mW (i.e., dBm), with 0.002-dB
-//			granularity. (R) (optional) (2-bytes)
+//			This attribute reports the current measurement of total downstream optical power. Its value is a
+//			2s complement integer referred to 1-mW (i.e., dBm), with 0.002-dB granularity. (Coding -32768 to
+//			+32767, where 0x00 = 0-dBm, 0x03e8 = +2-dBm, etc.) (R) (optional) (2-bytes)
 //
 //		Lower Optical Threshold
-//			Lower optical threshold: This attribute specifies the optical level that the RE uses to declare
-//			the downstream low received optical power alarm. Valid values are  -127-dBm (coded as 254) to
-//			0-dBm (coded as 0) in 0.5-dB increments. The default value 0xFF selects the RE's internal
-//			policy. (R,-W) (optional) (1-byte)
+//			This attribute specifies the optical level that the RE uses to declare the downstream low
+//			received optical power alarm. Valid values are  -127-dBm (coded as 254) to 0-dBm (coded as 0) in
+//			0.5-dB increments. The default value 0xFF selects the RE's internal policy. (R,-W) (optional)
+//			(1-byte)
 //
 //		Upper Optical Threshold
-//			Upper optical threshold: This attribute specifies the optical level that the RE uses to declare
-//			the downstream high received optical power alarm. Valid values are  -127-dBm (coded as 254) to
-//			0-dBm (coded as 0) in 0.5 dB increments. The default value 0xFF selects the RE's internal
-//			policy. (R,-W) (optional) (1-byte)
+//			This attribute specifies the optical level that the RE uses to declare the downstream high
+//			received optical power alarm. Valid values are  -127-dBm (coded as 254) to 0-dBm (coded as 0) in
+//			0.5 dB increments. The default value 0xFF selects the RE's internal policy. (R,-W) (optional)
+//			(1-byte)
 //
 //		Transmit Optical Level
-//			Transmit optical level: This attribute reports the current measurement of mean optical launch
-//			power. Its value is a 2s complement integer referred to 1-mW (i.e., dBm), with 0.002-dB
-//			granularity. (R) (optional) (2-bytes)
+//			This attribute reports the current measurement of mean optical launch power. Its value is a 2s
+//			complement integer referred to 1-mW (i.e., dBm), with 0.002-dB granularity. (Coding -32768 to
+//			+32767, where 0x00 = 0-dBm, 0x03e8 = +2-dBm, etc.) (R) (optional) (2-bytes)
 //
 //		Lower Transmit Power Threshold
-//			Lower transmit power threshold: This attribute specifies the minimum mean optical launch power
-//			that the RE uses to declare the low transmit optical power alarm. Its value is a 2s-complement
-//			integer referred to 1-mW (i.e., dBm), with 0.5-dB granularity. The default value 0x7F selects
-//			the RE's internal policy. (R,-W) (optional) (1-byte)
+//			This attribute specifies the minimum mean optical launch power that the RE uses to declare the
+//			low transmit optical power alarm. Its value is a 2s-complement integer referred to 1-mW (i.e.,
+//			dBm), with 0.5-dB granularity. The default value 0x7F selects the RE's internal policy. (R,-W)
+//			(optional) (1-byte)
 //
 //		Upper Transmit Power Threshold
-//			Upper transmit power threshold: This attribute specifies the maximum mean optical launch power
-//			that the RE uses to declare the high transmit optical power alarm. Its value is a 2s-complement
-//			integer referred to 1-mW (i.e., dBm), with 0.5-dB granularity. The default value 0x7F selects
-//			the RE's internal policy. (R,-W) (optional) (1-byte)
+//			This attribute specifies the maximum mean optical launch power that the RE uses to declare the
+//			high transmit optical power alarm. Its value is a 2s-complement integer referred to 1-mW (i.e.,
+//			dBm), with 0.5-dB granularity. The default value 0x7F selects the RE's internal policy. (R,-W)
+//			(optional) (1-byte)
 //
 //		Usage Mode
+//			In a mid-span PON RE, an R'/S' interface may be used as the PON interface for the embedded
+//			management ONU or the uplink interface for an S'/R' interface. This attribute specifies the
+//			usage of the R'/S' interface. (R,-W) (mandatory) (1-byte)
+//
+//			0	Disable
+//
+//			1	This R'/S' interface is used as the uplink for the embedded management ONU
+//
+//			2	This R'/S' interface is used as the uplink for one or more PPTP RE UNI(s)
+//
 //			3	This R'/S' interface is used as the uplink for both the embedded management ONU and one or
 //			more PPTP RE UNI(s) (in a time division fashion).
 //
 //		Target Upstream Frequency
-//			Target upstream frequency: This attribute specifies the frequency of the converted upstream
-//			signal on the optical trunk line (OTL), in gigahertz. The converted frequency must conform to
-//			the frequency plan specified in [ITUT G.984.6]. The value 0 means that the upstream signal
-//			frequency remains the same as the original frequency; no frequency conversion is done. If the RE
-//			does not support provisionable upstream frequency (wavelength), this attribute should take the
-//			fixed value representing the RE's capability and the RE should deny attempts to set the value of
-//			the attribute. If the RE does support provisionable upstream frequency conversion, the default
-//			value of this attribute is 0. (R, W) (optional) (4 bytes).
+//			This attribute specifies the frequency of the converted upstream signal on the optical trunk
+//			line (OTL), in gigahertz. The converted frequency must conform to the frequency plan specified
+//			in [ITUT G.984.6]. The value 0 means that the upstream signal frequency remains the same as the
+//			original frequency; no frequency conversion is done. If the RE does not support provisionable
+//			upstream frequency (wavelength), this attribute should take the fixed value representing the
+//			RE's capability and the RE should deny attempts to set the value of the attribute. If the RE
+//			does support provisionable upstream frequency conversion, the default value of this attribute is
+//			0. (R, W) (optional) (4 bytes).
 //
 //		Target Downstream Frequency
-//			Target downstream frequency: This attribute specifies the frequency of the downstream signal
-//			received by the RE on the OTL, in gigahertz. The incoming frequency must conform to the
-//			frequency plan specified in [ITUT G.984.6]. The default value 0 means that the downstream
-//			frequency remains the same as its original frequency; no frequency conversion is done. If the RE
-//			does not support provisionable downstream frequency selectivity, this attribute should take the
-//			fixed value representing the RE's capability, and the RE should deny attempts to set the value
-//			of the attribute. If the RE does support provisionable downstream frequency selectivity, the
-//			default value of this attribute is 0. (R, W) (optional) (4 bytes).
+//			This attribute specifies the frequency of the downstream signal received by the RE on the OTL,
+//			in gigahertz. The incoming frequency must conform to the frequency plan specified in [ITUT
+//			G.984.6]. The default value 0 means that the downstream frequency remains the same as its
+//			original frequency; no frequency conversion is done. If the RE does not support provisionable
+//			downstream frequency selectivity, this attribute should take the fixed value representing the
+//			RE's capability, and the RE should deny attempts to set the value of the attribute. If the RE
+//			does support provisionable downstream frequency selectivity, the default value of this attribute
+//			is 0. (R, W) (optional) (4 bytes).
 //
 //		Upstream Signal Transmission Mode
-//			Upstream signal transmission mode: When true, this Boolean attribute enables conversion from
-//			burst mode to continuous mode. The default value false specifies burst mode upstream
-//			transmission. If the RE does not have the ability to convert from burst to continuous mode
-//			transmission, it should deny attempts to set this attribute to true. (R, W) (optional) (1 byte)
+//			When true, this Boolean attribute enables conversion from burst mode to continuous mode. The
+//			default value false specifies burst mode upstream transmission. If the RE does not have the
+//			ability to convert from burst to continuous mode transmission, it should deny attempts to set
+//			this attribute to true. (R, W) (optional) (1 byte)
 //
 type ReAniG struct {
 	ManagedEntityDefinition
diff --git a/generated/recommonamplifierparameters.go b/generated/recommonamplifierparameters.go
index bc83606..d5149b9 100644
--- a/generated/recommonamplifierparameters.go
+++ b/generated/recommonamplifierparameters.go
@@ -27,11 +27,11 @@
 
 // ReCommonAmplifierParametersClassID is the 16-bit ID for the OMCI
 // Managed entity RE common amplifier parameters
-const ReCommonAmplifierParametersClassID ClassID = ClassID(328)
+const ReCommonAmplifierParametersClassID = ClassID(328) // 0x0148
 
 var recommonamplifierparametersBME *ManagedEntityDefinition
 
-// ReCommonAmplifierParameters (class ID #328)
+// ReCommonAmplifierParameters (Class ID: #328 / 0x0148)
 //	This ME organizes data associated with each OA supported by the RE. The management ONU
 //	automatically creates one instance of this ME for each upstream or downstream OA.
 //
@@ -41,66 +41,66 @@
 //
 //	Attributes
 //		Managed Entity Id
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of an upstream or downstream OA. The first byte is the slot ID
+//			(defined in clause 9.1.5). The second byte is the port ID. (R)-(mandatory) (2-bytes)
+//
 //			NOTE - The type of the linked ME can be determined by uniqueness of slot and port.
 //
 //		Gain
-//			Gain:	This attribute reports the current measurement of the OA's gain, in decibels. Its value is
-//			a 2s complement integer with 0.25-dB granularity, and with a range from -32-dB to 31.5-dB. The
-//			value 0x7F indicates that the current measured gain is 0, i.e., negative infinity in decibels
-//			terms. (R) (optional) (1-byte)
+//			This attribute reports the current measurement of the OA's gain, in decibels. Its value is a 2s
+//			complement integer with 0.25-dB granularity, and with a range from -32-dB to 31.5-dB. The value
+//			0x7F indicates that the current measured gain is 0, i.e., negative infinity in decibels terms.
+//			(R) (optional) (1-byte)
 //
 //		Lower Gain Threshold
-//			Lower gain threshold: This attribute specifies the gain the RE uses to declare the low gain
-//			alarm. Valid values are 0-dB (coded as 0x00) to 63.5-dB (coded as 0xFE). The default value 0xFF
-//			selects the RE's internal policy. (R,-W) (optional) (1-byte)
+//			This attribute specifies the gain the RE uses to declare the low gain alarm. Valid values are
+//			0-dB (coded as 0x00) to 63.5-dB (coded as 0xFE). The default value 0xFF selects the RE's
+//			internal policy. (R,-W) (optional) (1-byte)
 //
 //		Upper Gain Threshold
-//			Upper gain threshold: This attribute specifies the gain the RE uses to declare the high gain
-//			alarm. Valid values are 0-dB (coded as 0x00) to 63.5-dB (coded as 0xFE). The default value 0xFF
-//			selects the RE's internal policy. (R,-W) (optional) (1-byte)
+//			This attribute specifies the gain the RE uses to declare the high gain alarm. Valid values are
+//			0-dB (coded as 0x00) to 63.5-dB (coded as 0xFE). The default value 0xFF selects the RE's
+//			internal policy. (R,-W) (optional) (1-byte)
 //
 //		Target Gain
-//			Target gain:	This attribute specifies the target gain, when the operational mode of the parent
-//			RE downstream or upstream amplifier is set to constant gain mode. Valid values are 0-dB (coded
-//			as 0x00) to 63.5-dB (coded as 0xFE). The default value 0xFF selects the RE's internal policy.
-//			(R,-W) (optional) (1-byte)
-//
-//		Device Temperature
-//			Device temperature: This attribute reports the temperature in degrees Celcius of the active
-//			device (SOA or pump) in the OA. Its value is a 2s complement integer with granularity
-//			1/256-degree-C. (R) (optional) (2-bytes)
-//
-//		Lower Device Temperature Threshold
-//			Lower device temperature threshold: This attribute is a 2s complement integer that specifies the
-//			temperature the RE uses to declare the low temperature alarm. Valid values are -64 to
-//			+63-degree-C in 0.5-degree-C increments. The default value 0x7F selects the RE's internal
-//			policy. (R,-W) (optional) (1-byte)
-//
-//		Upper Device Temperature Threshold
-//			Upper device temperature threshold: This attribute is a 2s complement integer that specifies the
-//			temperature the RE uses to declare the high temperature alarm. Valid values are -64 to
-//			+63-degree-C in 0.5-degree-C increments. The default value 0x7F selects the RE's internal
-//			policy. (R,-W) (optional) (1-byte)
-//
-//		Device Bias Current
-//			Device bias current: This attribute contains the measured bias current applied to the SOA or
-//			pump laser. Its value is an unsigned integer with granularity 2-mA. Valid values are 0 to
-//			512-mA. (R) (optional) (1-byte)
-//
-//		Amplifier Saturation Output Power
-//			Amplifier saturation output power: This attribute reports the saturation output power of the
-//			amplifier as specified by the manufacturer. Its value is an unsigned integer referred to 1-mW
-//			(i.e., dBm), with 0.1-dB granularity. (R) (optional) (2-bytes)
-//
-//		Amplifier Noise Figure
-//			Amplifier noise figure: This attribute reports the intrinsic noise figure of the amplifier, as
-//			specified by the manufacturer. Its value is an unsigned integer with 0.1-dB granularity (R)
+//			This attribute specifies the target gain, when the operational mode of the parent RE downstream
+//			or upstream amplifier is set to constant gain mode. Valid values are 0-dB (coded as 0x00) to
+//			63.5-dB (coded as 0xFE). The default value 0xFF selects the RE's internal policy. (R,-W)
 //			(optional) (1-byte)
 //
+//		Device Temperature
+//			This attribute reports the temperature in degrees Celcius of the active device (SOA or pump) in
+//			the OA. Its value is a 2s complement integer with granularity 1/256-degree-C. (R) (optional)
+//			(2-bytes)
+//
+//		Lower Device Temperature Threshold
+//			This attribute is a 2s complement integer that specifies the temperature the RE uses to declare
+//			the low temperature alarm. Valid values are -64 to +63-degree-C in 0.5-degree-C increments. The
+//			default value 0x7F selects the RE's internal policy. (R,-W) (optional) (1-byte)
+//
+//		Upper Device Temperature Threshold
+//			This attribute is a 2s complement integer that specifies the temperature the RE uses to declare
+//			the high temperature alarm. Valid values are -64 to +63-degree-C in 0.5-degree-C increments. The
+//			default value 0x7F selects the RE's internal policy. (R,-W) (optional) (1-byte)
+//
+//		Device Bias Current
+//			This attribute contains the measured bias current applied to the SOA or pump laser. Its value is
+//			an unsigned integer with granularity 2-mA. Valid values are 0 to 512-mA. (R) (optional) (1-byte)
+//
+//		Amplifier Saturation Output Power
+//			This attribute reports the saturation output power of the amplifier as specified by the
+//			manufacturer. Its value is an unsigned integer referred to 1-mW (i.e., dBm), with 0.1-dB
+//			granularity. (R) (optional) (2-bytes)
+//
+//		Amplifier Noise Figure
+//			This attribute reports the intrinsic noise figure of the amplifier, as specified by the
+//			manufacturer. Its value is an unsigned integer with 0.1-dB granularity (R) (optional) (1-byte)
+//
 //		Amplifier Saturation Gain
-//			Amplifier saturation gain: This attribute reports the gain of the amplifier at saturation, as
-//			specified by the manufacturer. Its value is an unsigned integer with 0.25-dB granularity, and
-//			with a range from 0 to 63.75-dB. (R) (optional) (1-byte)
+//			This attribute reports the gain of the amplifier at saturation, as specified by the
+//			manufacturer. Its value is an unsigned integer with 0.25-dB granularity, and with a range from 0
+//			to 63.75-dB. (R) (optional) (1-byte)
 //
 type ReCommonAmplifierParameters struct {
 	ManagedEntityDefinition
diff --git a/generated/redownstreamamplifier.go b/generated/redownstreamamplifier.go
index f5176d9..d85e3a7 100644
--- a/generated/redownstreamamplifier.go
+++ b/generated/redownstreamamplifier.go
@@ -27,11 +27,11 @@
 
 // ReDownstreamAmplifierClassID is the 16-bit ID for the OMCI
 // Managed entity RE downstream amplifier
-const ReDownstreamAmplifierClassID ClassID = ClassID(316)
+const ReDownstreamAmplifierClassID = ClassID(316) // 0x013c
 
 var redownstreamamplifierBME *ManagedEntityDefinition
 
-// ReDownstreamAmplifier (class ID #316)
+// ReDownstreamAmplifier (Class ID: #316 / 0x013c)
 //	This ME organizes data associated with each OA for downstream data supported by the RE. The
 //	management ONU automatically creates one instance of this ME for each downstream OA as follows.
 //
@@ -57,10 +57,17 @@
 //
 //	Attributes
 //		Managed Entity Id
+//			This attribute uniquely identifies each instance of this ME. Its value indicates the physical
+//			position of the downstream OA. The first byte is the slot ID (defined in clause 9.1.5 of [ITU-T
+//			G.984.4]). The second byte is the port ID. (R) (mandatory) (2-bytes)
+//
 //			NOTE 1 - This ME ID may be identical to that of an RE ANI-G if it shares the same physical slot-
 //			port.
 //
 //		Administrative State
+//			This attribute locks (1) and unlocks (0) the functions performed by this ME. Administrative
+//			state is further described in clause A.1.6. (R,-W) (mandatory) (1-byte)
+//
 //			NOTE 2- When an RE supports multiple PONs, or protected access to a single PON, its primary
 //			ANI-G cannot be completely shut down, due to a loss of the management communications capability.
 //			Complete blocking of service and removal of power may nevertheless be appropriate for secondary
@@ -69,59 +76,67 @@
 //			downstream amplifier, be it either primary or secondary.
 //
 //		Operational State
-//			Operational state: This attribute indicates whether the ME is capable of performing its
-//			function. Valid values are enabled (0) and disabled (1). (R) (optional) (1-byte)
+//			This attribute indicates whether the ME is capable of performing its function. Valid values are
+//			enabled (0) and disabled (1). (R) (optional) (1-byte)
 //
 //		Arc
-//			ARC:	See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Arc Interval
-//			ARC interval: See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Operational Mode
+//			This attribute indicates the operational mode as follows.
+//
+//			0	Constant gain
+//
+//			1	Constant output power
+//
+//			2	Autonomous
+//
 //			(R,W) (mandatory) (1-byte)
 //
 //		Input Optical Signal Level
-//			Input optical signal level: This attribute reports the current measurement of the input optical
-//			signal power of the downstream OA. Its value is a 2s-complement integer referred to 1-mW (i.e.,
-//			dBm), with 0.002-dB granularity. (R) (optional) (2-bytes)
+//			This attribute reports the current measurement of the input optical signal power of the
+//			downstream OA. Its value is a 2s-complement integer referred to 1-mW (i.e., dBm), with 0.002-dB
+//			granularity. (Coding -32768 to +32767, where 0x00 = 0-dBm, 0x03e8 = +2-dBm, etc.) (R) (optional)
+//			(2-bytes)
 //
 //		Lower Input Optical Threshold
-//			Lower input optical threshold: This attribute specifies the optical level the RE uses to declare
-//			the low received optical power alarm. Valid values are -127-dBm (coded as 254) to 0-dBm (coded
-//			as 0) in 0.5-dB increments. The default value 0xFF selects the RE's internal policy. (R,-W)
-//			(optional) (1-byte)
+//			This attribute specifies the optical level the RE uses to declare the low received optical power
+//			alarm. Valid values are -127-dBm (coded as 254) to 0-dBm (coded as 0) in 0.5-dB increments. The
+//			default value 0xFF selects the RE's internal policy. (R,-W) (optional) (1-byte)
 //
 //		Upper Input Optical Threshold
-//			Upper input optical threshold: This attribute specifies the optical level the RE uses to declare
-//			the high received optical power alarm. Valid values are -127-dBm (coded as 254) to 0-dBm (coded
-//			as 0) in 0.5-dB increments. The default value 0xFF selects the RE's internal policy. (R,-W)
-//			(optional) (1-byte)
+//			This attribute specifies the optical level the RE uses to declare the high received optical
+//			power alarm. Valid values are -127-dBm (coded as 254) to 0-dBm (coded as 0) in 0.5-dB
+//			increments. The default value 0xFF selects the RE's internal policy. (R,-W) (optional) (1-byte)
 //
 //		Output Optical Signal Level
-//			Output optical signal level: This attribute reports the current measurement of the mean optical
-//			launch power of the downstream OA. Its value is a 2s-complement integer referred to 1-mW (i.e.,
-//			dBm), with 0.002-dB granularity. (R) (optional) (2-bytes)
+//			This attribute reports the current measurement of the mean optical launch power of the
+//			downstream OA. Its value is a 2s-complement integer referred to 1-mW (i.e., dBm), with 0.002-dB
+//			granularity. (Coding -32768 to +32767, where 0x00 = 0-dBm, 0x03e8 = +2-dBm, etc.) (R) (optional)
+//			(2-bytes)
 //
 //		Lower Output Optical Threshold
-//			Lower output optical threshold: This attribute specifies the minimum mean optical launch power
-//			that the RE uses to declare the low transmit optical power alarm. Its value is a 2s complement
-//			integer referred to 1-mW (i.e., dBm), with 0.5-dB granularity. The default value 0x7F selects
-//			the RE's internal policy. (R,-W) (optional) (1-byte)
+//			This attribute specifies the minimum mean optical launch power that the RE uses to declare the
+//			low transmit optical power alarm. Its value is a 2s complement integer referred to 1-mW (i.e.,
+//			dBm), with 0.5-dB granularity. The default value 0x7F selects the RE's internal policy. (R,-W)
+//			(optional) (1-byte)
 //
 //		Upper Output Optical Threshold
-//			Upper output optical threshold: This attribute specifies the maximum mean optical launch power
-//			that the RE uses to declare the high transmit optical power alarm. Its value is a 2s complement
-//			integer referred to 1-mW (i.e., dBm), with 0.5-dB granularity. The default value 0x7F selects
-//			the RE's internal policy. (R,-W) (optional) (1-byte)
+//			This attribute specifies the maximum mean optical launch power that the RE uses to declare the
+//			high transmit optical power alarm. Its value is a 2s complement integer referred to 1-mW (i.e.,
+//			dBm), with 0.5-dB granularity. The default value 0x7F selects the RE's internal policy. (R,-W)
+//			(optional) (1-byte)
 //
 //		R'S' Splitter Coupling Ratio
-//			R'S' splitter coupling ratio: This attribute reports the coupling ratio of the splitter at the
-//			R'/S' interface that connects the embedded management ONU and the amplifiers to the OTL. Valid
-//			values are 99:1 (coded as 99-decimal) to 1:99 (coded as 1 decimal), where the first value is the
-//			value encoded and is the percentage of the optical signal connected to the amplifier. The
-//			default value 0xFF indicates that there is no splitter connected to this upstream/downstream
-//			amplifier pair. (R) (optional) (1-byte)
+//			This attribute reports the coupling ratio of the splitter at the R'/S' interface that connects
+//			the embedded management ONU and the amplifiers to the OTL. Valid values are 99:1 (coded as
+//			99-decimal) to 1:99 (coded as 1 decimal), where the first value is the value encoded and is the
+//			percentage of the optical signal connected to the amplifier. The default value 0xFF indicates
+//			that there is no splitter connected to this upstream/downstream amplifier pair. (R) (optional)
+//			(1-byte)
 //
 type ReDownstreamAmplifier struct {
 	ManagedEntityDefinition
diff --git a/generated/reupstreamamplifier.go b/generated/reupstreamamplifier.go
index df21ac2..32f3e62 100644
--- a/generated/reupstreamamplifier.go
+++ b/generated/reupstreamamplifier.go
@@ -27,11 +27,11 @@
 
 // ReUpstreamAmplifierClassID is the 16-bit ID for the OMCI
 // Managed entity RE upstream amplifier
-const ReUpstreamAmplifierClassID ClassID = ClassID(315)
+const ReUpstreamAmplifierClassID = ClassID(315) // 0x013b
 
 var reupstreamamplifierBME *ManagedEntityDefinition
 
-// ReUpstreamAmplifier (class ID #315)
+// ReUpstreamAmplifier (Class ID: #315 / 0x013b)
 //	This ME organizes data associated with each upstream RE optical amplifier (OA) supported by the
 //	RE. The management ONU automatically creates one instance of this ME for each upstream OA as
 //	follows.
@@ -58,77 +58,91 @@
 //
 //	Attributes
 //		Managed Entity Id
+//			This attribute uniquely identifies each instance of this ME. Its value indicates the physical
+//			position of the upstream OA. The first byte is the slot ID (defined in clause 9.1.5). The second
+//			byte is the port ID. (R) (mandatory) (2-bytes)
+//
 //			NOTE 1 - This ME ID may be identical to that of a PPTP RE UNI if it shares the same physical
 //			slot and port.
 //
 //		Administrative State
+//			This attribute locks (1) and unlocks (0) the functions performed by this ME. Administrative
+//			state is further described in clause A.1.6. (R,-W) (mandatory) (1-byte)
+//
 //			NOTE 2 - Administrative lock of an RE upstream amplifier results in LOS from any downstream
 //			ONUs.
 //
 //		Operational State
-//			Operational state: This attribute indicates whether the ME is capable of performing its
-//			function. Valid values are enabled (0) and disabled (1). (R) (optional) (1-byte)
+//			This attribute indicates whether the ME is capable of performing its function. Valid values are
+//			enabled (0) and disabled (1). (R) (optional) (1-byte)
 //
 //		Operational Mode
+//			This attribute indicates the operational mode as follows.
+//
+//			0	Constant gain
+//
+//			1	Constant output power
+//
+//			2	Autonomous
+//
 //			(R,-W) (mandatory) (1-byte)
 //
 //		Arc
-//			ARC:	See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Arc Interval
-//			ARC interval: See clause A.1.4.3. (R,-W) (optional) (1-byte)
+//			See clause A.1.4.3. (R,-W) (optional) (1-byte)
 //
 //		Re Downstream Amplifier Pointer
-//			RE downstream amplifier pointer: This attribute points to an RE downstream amplifier instance.
-//			The default value is 0xFFFF, a null pointer. (R,-W) (mandatory) (2-bytes)
+//			This attribute points to an RE downstream amplifier instance. The default value is 0xFFFF, a
+//			null pointer. (R,-W) (mandatory) (2-bytes)
 //
 //		Total Optical Receive Signal Level Table
-//			Total optical receive signal level table: This table attribute reports a series of measurements
-//			of time-averaged input upstream optical signal power. The measurement circuit should have a
-//			temporal response similar to a simple 1 pole low pass filter, with an effective time constant on
-//			the order of a GTC frame time. Each table entry has a 2-byte frame counter field (most
-//			significant end), and a 2-byte power measurement field. The frame counter field contains the
-//			least significant 16-bits of the superframe counter received closest to the time of the
-//			measurement. The power measurement field is a 2s-complement integer referred to 1-mW (i.e.,
-//			dBm), with 0.002-dB granularity. The RE equipment should add entries to this table as frequently
-//			as is reasonable. The RE should clear the table once it is read by the OLT. (R) (optional) (4-*
-//			N-bytes, where N is the number of measurements present.)
+//			This table attribute reports a series of measurements of time-averaged input upstream optical
+//			signal power. The measurement circuit should have a temporal response similar to a simple 1 pole
+//			low pass filter, with an effective time constant on the order of a GTC frame time. Each table
+//			entry has a 2-byte frame counter field (most significant end), and a 2-byte power measurement
+//			field. The frame counter field contains the least significant 16-bits of the superframe counter
+//			received closest to the time of the measurement. The power measurement field is a 2s-complement
+//			integer referred to 1-mW (i.e., dBm), with 0.002-dB granularity. (Coding -32768 to +32767, where
+//			0x00 = 0-dBm, 0x03e8 = +2-dBm, etc.) The RE equipment should add entries to this table as
+//			frequently as is reasonable. The RE should clear the table once it is read by the OLT. (R)
+//			(optional) (4-* N-bytes, where N is the number of measurements present.)
 //
 //		Per Burst Receive Signal Level Table
-//			Per burst receive signal level table: This table attribute reports the most recent measurement
-//			of received burst upstream optical signal power. Each table entry has a 2-byte ONU-ID field
-//			(most significant end), and a 2-byte power measurement field. The power measurement field is a
-//			2s-complement integer referred to 1-mW (i.e.,-dBm), with 0.002-dB granularity. (R) (optional)
-//			(4-* N-bytes, where N is the number of distinct ONUs connected to the S'/R' interface.)
+//			This table attribute reports the most recent measurement of received burst upstream optical
+//			signal power. Each table entry has a 2-byte ONU-ID field (most significant end), and a 2-byte
+//			power measurement field. The power measurement field is a 2s-complement integer referred to 1-mW
+//			(i.e.,-dBm), with 0.002-dB granularity. (Coding -32768 to +32767, where 0x00 = 0-dBm, 0x03e8 =
+//			+2-dBm, etc.) (R) (optional) (4-* N-bytes, where N is the number of distinct ONUs connected to
+//			the S'/R' interface.)
 //
 //		Lower Receive Optical Threshold
-//			Lower receive optical threshold: This attribute specifies the optical level that the RE uses to
-//			declare the low received optical power alarm. Valid values are -127-dBm (coded as 254) to 0-dBm
-//			(coded as 0) in 0.5-dB increments. The default value 0xFF selects the RE's internal policy.
-//			(R,-W) (optional) (1-byte)
+//			This attribute specifies the optical level that the RE uses to declare the low received optical
+//			power alarm. Valid values are -127-dBm (coded as 254) to 0-dBm (coded as 0) in 0.5-dB
+//			increments. The default value 0xFF selects the RE's internal policy. (R,-W) (optional) (1-byte)
 //
 //		Upper Receive Optical Threshold
-//			Upper receive optical threshold: This attribute specifies the optical level that the RE uses to
-//			declare the high received optical power alarm. Valid values are -127-dBm (coded as 254) to 0-dBm
-//			(coded as 0) in 0.5-dB increments. The default value 0xFF selects the RE's internal policy.
-//			(R,-W) (optional) (1-byte)
+//			This attribute specifies the optical level that the RE uses to declare the high received optical
+//			power alarm. Valid values are -127-dBm (coded as 254) to 0-dBm (coded as 0) in 0.5-dB
+//			increments. The default value 0xFF selects the RE's internal policy. (R,-W) (optional) (1-byte)
 //
 //		Transmit Optical Signal Level
-//			Transmit optical signal level: This attribute reports the current measurement of the mean
-//			optical launch power of the upstream OA. Its value is a 2s-complement integer referred to 1-mW
-//			(i.e., dBm), with 0.002-dB granularity. (R) (optional) (2-bytes)
+//			This attribute reports the current measurement of the mean optical launch power of the upstream
+//			OA. Its value is a 2s-complement integer referred to 1-mW (i.e., dBm), with 0.002-dB
+//			granularity. (R) (optional) (2-bytes)
 //
 //		Lower Transmit Optical Threshold
-//			Lower transmit optical threshold: This attribute specifies the minimum mean optical launch power
-//			that the RE uses to declare the low transmit optical power alarm. Its value is a 2s-complement
-//			integer referred to 1-mW (i.e., dBm), with 0.5-dB granularity. The default value 0x7F selects
-//			the RE's internal policy. (R,-W) (optional) (1-byte)
+//			This attribute specifies the minimum mean optical launch power that the RE uses to declare the
+//			low transmit optical power alarm. Its value is a 2s-complement integer referred to 1-mW (i.e.,
+//			dBm), with 0.5-dB granularity. The default value 0x7F selects the RE's internal policy. (R,-W)
+//			(optional) (1-byte)
 //
 //		Upper Transmit Optical Threshold
-//			Upper transmit optical threshold: This attribute specifies the maximum mean optical launch power
-//			that the RE uses to declare the high transmit optical power alarm. Its value is a 2s complement
-//			integer referred to 1-mW (i.e., dBm), with 0.5-dB granularity. The default value 0x7F selects
-//			the RE's internal policy. (R,-W) (optional) (1-byte)
+//			This attribute specifies the maximum mean optical launch power that the RE uses to declare the
+//			high transmit optical power alarm. Its value is a 2s complement integer referred to 1-mW (i.e.,
+//			dBm), with 0.5-dB granularity. The default value 0x7F selects the RE's internal policy. (R,-W)
+//			(optional) (1-byte)
 //
 type ReUpstreamAmplifier struct {
 	ManagedEntityDefinition
diff --git a/generated/rtpperformancemonitoringhistorydata.go b/generated/rtpperformancemonitoringhistorydata.go
index ba4fd8b..3252376 100644
--- a/generated/rtpperformancemonitoringhistorydata.go
+++ b/generated/rtpperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // RtpPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity RTP performance monitoring history data
-const RtpPerformanceMonitoringHistoryDataClassID ClassID = ClassID(144)
+const RtpPerformanceMonitoringHistoryDataClassID = ClassID(144) // 0x0090
 
 var rtpperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// RtpPerformanceMonitoringHistoryData (class ID #144)
+// RtpPerformanceMonitoringHistoryData (Class ID: #144 / 0x0090)
 //	This ME collects PM data related to an RTP session. Instances of this ME are created and deleted
 //	by the OLT.
 //
@@ -42,13 +42,11 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP POTS UNI ME. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP POTS UNI ME. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -56,18 +54,17 @@
 //			data 2 ME is optional. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Rtp Errors
-//			RTP errors:	This attribute counts RTP packet errors. (R) (mandatory) (4-bytes)
+//			This attribute counts RTP packet errors. (R) (mandatory) (4-bytes)
 //
 //		Packet Loss
-//			Packet loss:	This attribute represents the fraction of packets lost. This attribute is
-//			calculated at the end of the 15-min interval, and is undefined under the get current data
-//			action. The value 0 indicates no packet loss, scaling linearly to 0xFFFF FFFF to indicate 100%
-//			packet loss (zero divided by zero is defined to be zero). (R) (mandatory) (4-bytes)
+//			This attribute represents the fraction of packets lost. This attribute is calculated at the end
+//			of the 15-min interval, and is undefined under the get current data action. The value 0
+//			indicates no packet loss, scaling linearly to 0xFFFF FFFF to indicate 100% packet loss (zero
+//			divided by zero is defined to be zero). (R) (mandatory) (4-bytes)
 //
 //		Maximum Jitter
-//			Maximum jitter: This attribute is a high water-mark that represents the maximum jitter
-//			identified during the measured interval, expressed in RTP timestamp units. (R) (mandatory)
-//			(4-bytes)
+//			This attribute is a high water-mark that represents the maximum jitter identified during the
+//			measured interval, expressed in RTP timestamp units. (R) (mandatory) (4-bytes)
 //
 //		Maximum Time Between Real_Time Transport Control Protocol Rtcp Packets
 //			Maximum time between real-time transport control protocol (RTCP) packets: This attribute is a
@@ -75,17 +72,16 @@
 //			interval, in milliseconds. (R) (mandatory) (4-bytes)
 //
 //		Buffer Underflows
-//			Buffer underflows: This attribute counts the number of times the reassembly buffer underflows.
-//			In the case of continuous underflow caused by a loss of IP packets, a single buffer underflow
-//			should be counted. If the IW function is implemented with multiple buffers, such as a packet
-//			level buffer and a bit level buffer, then the underflow of either buffer increments this
-//			counter. (R) (mandatory) (4-bytes)
+//			This attribute counts the number of times the reassembly buffer underflows. In the case of
+//			continuous underflow caused by a loss of IP packets, a single buffer underflow should be
+//			counted. If the IW function is implemented with multiple buffers, such as a packet level buffer
+//			and a bit level buffer, then the underflow of either buffer increments this counter. (R)
+//			(mandatory) (4-bytes)
 //
 //		Buffer Overflows
-//			Buffer overflows: This attribute counts the number of times the reassembly buffer overflows. If
-//			the IW function is implemented with multiple buffers, such as a packet level buffer and a bit
-//			level buffer, then the overflow of either buffer increments this counter. (R) (mandatory)
-//			(4-bytes)
+//			This attribute counts the number of times the reassembly buffer overflows. If the IW function is
+//			implemented with multiple buffers, such as a packet level buffer and a bit level buffer, then
+//			the overflow of either buffer increments this counter. (R) (mandatory) (4-bytes)
 //
 type RtpPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/rtpprofiledata.go b/generated/rtpprofiledata.go
index 0eb13aa..1bc4f00 100644
--- a/generated/rtpprofiledata.go
+++ b/generated/rtpprofiledata.go
@@ -27,11 +27,11 @@
 
 // RtpProfileDataClassID is the 16-bit ID for the OMCI
 // Managed entity RTP profile data
-const RtpProfileDataClassID ClassID = ClassID(143)
+const RtpProfileDataClassID = ClassID(143) // 0x008f
 
 var rtpprofiledataBME *ManagedEntityDefinition
 
-// RtpProfileData (class ID #143)
+// RtpProfileData (Class ID: #143 / 0x008f)
 //	This ME configures RTP. It is conditionally required for ONUs that offer VoIP service. If a non-
 //	OMCI interface is used to manage VoIP, this ME is unnecessary.
 //
@@ -43,41 +43,68 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Local Port Min
-//			Local port min: This attribute defines the base UDP port that should be used by RTP for voice
-//			traffic. The recommended default is 50000 (R,-W, set-by-create) (mandatory) (2-bytes)
+//			This attribute defines the base UDP port that should be used by RTP for voice traffic. The
+//			recommended default is 50000 (R,-W, set-by-create) (mandatory) (2-bytes)
 //
 //		Local Port Max
-//			Local port max: This attribute defines the highest UDP port used by RTP for voice traffic. The
-//			value must be greater than the local port minimum. The value 0 specifies that the local port
-//			maximum be equal to the local port minimum. (R,-W, set-by-create) (optional) (2-bytes)
+//			This attribute defines the highest UDP port used by RTP for voice traffic. The value must be
+//			greater than the local port minimum. The value 0 specifies that the local port maximum be equal
+//			to the local port minimum. (R,-W, set-by-create) (optional) (2-bytes)
 //
 //		Dscp Mark
-//			DSCP mark:	Diffserv code point to be used for outgoing RTP packets for this profile. The
-//			recommended default value is expedited forwarding (EF)-= 0x2E. (R,-W, setbycreate) (mandatory)
-//			(1-byte)
+//			Diffserv code point to be used for outgoing RTP packets for this profile. The recommended
+//			default value is expedited forwarding (EF)-= 0x2E. (R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Piggyback Events
+//			0	Disabled (recommended default)
+//
+//			1	Enabled
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
+//			Enables or disables RTP piggyback events.
+//
 //		Tone Events
+//			Enables or disables the handling of tones via RTP tone events per [IETF RFC 4733], (see also
+//			[IETF RFC 4734]).
+//
+//			0	Disabled (recommended default)
+//
+//			1	Enabled
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Dtmf Events
+//			0	Disabled
+//
+//			1	Enabled
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
+//			Enables or disables the handling of DTMF via RTP DTMF events per [IETF-RFC 4733], (see also
+//			[IETF RFC 4734]). This attribute is ignored unless the OOB DTMF attribute in the VoIP media
+//			profile is enabled.
+//
 //		Cas Events
+//			Enables or disables the handling of CAS via RTP CAS events per [IETF-RFC-4733], (see also [IETF
+//			RFC 4734]).
+//
+//			0	Disabled
+//
+//			1	Enabled
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Ip Host Config Pointer
-//			IP host config pointer: This optional pointer associates the bearer (voice) flow with an IP host
-//			config data or IPv6 host config data ME. If this attribute is not present or is not populated
-//			with a valid pointer value, the bearer flow uses the same IP stack that is used for signalling,
-//			indicated by the TCP/UDP pointer in the associated SIP agent or MGC config data. The default
-//			value is 0xFFFF, a null pointer. (R,-W) (optional) (2-bytes)
+//			This optional pointer associates the bearer (voice) flow with an IP host config data or IPv6
+//			host config data ME. If this attribute is not present or is not populated with a valid pointer
+//			value, the bearer flow uses the same IP stack that is used for signalling, indicated by the
+//			TCP/UDP pointer in the associated SIP agent or MGC config data. The default value is 0xFFFF, a
+//			null pointer. (R,-W) (optional) (2-bytes)
 //
 type RtpProfileData struct {
 	ManagedEntityDefinition
diff --git a/generated/rtppseudowireparameters.go b/generated/rtppseudowireparameters.go
index 3b0f568..472f754 100644
--- a/generated/rtppseudowireparameters.go
+++ b/generated/rtppseudowireparameters.go
@@ -27,11 +27,11 @@
 
 // RtpPseudowireParametersClassID is the 16-bit ID for the OMCI
 // Managed entity RTP pseudowire parameters
-const RtpPseudowireParametersClassID ClassID = ClassID(283)
+const RtpPseudowireParametersClassID = ClassID(283) // 0x011b
 
 var rtppseudowireparametersBME *ManagedEntityDefinition
 
-// RtpPseudowireParameters (class ID #283)
+// RtpPseudowireParameters (Class ID: #283 / 0x011b)
 //	If a pseudowire service uses RTP, the RTP pseudowire parameters ME provides configuration
 //	information for the RTP layer. Instances of this ME are created and deleted by the OLT. The use
 //	of RTP on a pseudowire is optional, and is determined by the existence of the RTP pseudowire
@@ -43,43 +43,52 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the pseudowire TP ME. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the pseudowire TP ME. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Clock Reference
-//			Clock reference: This attribute specifies the frequency of the common timing reference, in
-//			multiples of 8 kHz. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute specifies the frequency of the common timing reference, in multiples of 8 kHz.
+//			(R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Rtp Timestamp Mode
+//			This attribute determines the mode in which RTP timestamps are generated in the TDM to the PSN
+//			direction.
+//
+//			0	Unknown or not applicable.
+//
+//			1	Absolute. Timestamps are based on the timing of the incoming TDM signal.
+//
+//			2	Differential. Timestamps are based on the ONU's reference clock, which is understood to be
+//			stratum-traceable along with the reference clock at the far end.
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Ptype
-//			PTYPE:	This attribute specifies the RTP payload type in the TDM to the PSN direction. It
-//			comprises two 1-byte values. The first is for the payload channel, the second, for the optional
-//			separate signalling channel. Assignable PTYPEs lie in the dynamic range 96..127. If signalling
-//			is not transported in its own channel, the second value should be set to 0. (R,-W, setbycreate)
+//			This attribute specifies the RTP payload type in the TDM to the PSN direction. It comprises two
+//			1-byte values. The first is for the payload channel, the second, for the optional separate
+//			signalling channel. Assignable PTYPEs lie in the dynamic range 96..127. If signalling is not
+//			transported in its own channel, the second value should be set to 0. (R,-W, setbycreate)
 //			(mandatory) (2-bytes)
 //
 //		Ssrc
-//			SSRC:	This attribute specifies the RTP synchronization source in the TDM to the PSN direction.
-//			It comprises two 4-byte values. The first is for the payload channel, the second, for the
-//			optional separate signalling channel. If signalling is not transported in its own channel, the
-//			second value should be set to 0. (R,-W, setbycreate) (mandatory) (8-bytes)
+//			This attribute specifies the RTP synchronization source in the TDM to the PSN direction. It
+//			comprises two 4-byte values. The first is for the payload channel, the second, for the optional
+//			separate signalling channel. If signalling is not transported in its own channel, the second
+//			value should be set to 0. (R,-W, setbycreate) (mandatory) (8-bytes)
 //
 //		Expected Ptype
-//			Expected PTYPE: This attribute specifies the RTP payload type in the PSN to the TDM direction.
-//			The received payload type may be used to detect malformed packets. It comprises two 1-byte
-//			values. The first is for the payload channel, the second, for the optional separate signalling
-//			channel. To disable either or both of the check functions, set the corresponding value to its
-//			default value 0. (R,-W, setbycreate) (optional) (2-bytes)
+//			This attribute specifies the RTP payload type in the PSN to the TDM direction. The received
+//			payload type may be used to detect malformed packets. It comprises two 1-byte values. The first
+//			is for the payload channel, the second, for the optional separate signalling channel. To disable
+//			either or both of the check functions, set the corresponding value to its default value 0.
+//			(R,-W, setbycreate) (optional) (2-bytes)
 //
 //		Expected Ssrc
-//			Expected SSRC: This attribute specifies the RTP synchronization source in the PSN to the TDM
-//			direction. The received SSRC may be used to detect misconnection (stray packets). It comprises
-//			two 4-byte values. The first is for the payload channel, the second, for the optional separate
-//			signalling channel. To disable either or both of the check functions, set the corresponding
-//			value to its default value 0. (R,-W, setbycreate) (optional) (8-bytes)
+//			This attribute specifies the RTP synchronization source in the PSN to the TDM direction. The
+//			received SSRC may be used to detect misconnection (stray packets). It comprises two 4-byte
+//			values. The first is for the payload channel, the second, for the optional separate signalling
+//			channel. To disable either or both of the check functions, set the corresponding value to its
+//			default value 0. (R,-W, setbycreate) (optional) (8-bytes)
 //
 type RtpPseudowireParameters struct {
 	ManagedEntityDefinition
diff --git a/generated/sipagentconfigdata.go b/generated/sipagentconfigdata.go
index 4594544..ec9d2c2 100644
--- a/generated/sipagentconfigdata.go
+++ b/generated/sipagentconfigdata.go
@@ -27,11 +27,11 @@
 
 // SipAgentConfigDataClassID is the 16-bit ID for the OMCI
 // Managed entity SIP agent config data
-const SipAgentConfigDataClassID ClassID = ClassID(150)
+const SipAgentConfigDataClassID = ClassID(150) // 0x0096
 
 var sipagentconfigdataBME *ManagedEntityDefinition
 
-// SipAgentConfigData (class ID #150)
+// SipAgentConfigData (Class ID: #150 / 0x0096)
 //	The SIP agent config data ME models a SIP signalling agent. It defines the configuration
 //	necessary to establish communication for signalling between the SIP user agent (UA) and a SIP
 //	server.
@@ -49,35 +49,31 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Proxy Server Address Pointer
-//			Proxy server address pointer: This attribute points to a large string ME that contains the name
-//			(IP address or URI) of the SIP proxy server for SIP signalling messages. (R,-W, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute points to a large string ME that contains the name (IP address or URI) of the SIP
+//			proxy server for SIP signalling messages. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Outbound Proxy Address Pointer
-//			Outbound proxy address pointer: An outbound SIP proxy may or may not be required within a given
-//			network. If an outbound SIP proxy is used, the outbound proxy address pointer attribute must be
-//			set to point to a valid large string ME that contains the name (IP address or URI) of the
-//			outbound proxy server for SIP signalling messages. If an outbound SIP proxy is not used, the
-//			outbound proxy address pointer attribute must be set to a null pointer. (R,-W, setbycreate)
-//			(mandatory) (2-bytes)
+//			An outbound SIP proxy may or may not be required within a given network. If an outbound SIP
+//			proxy is used, the outbound proxy address pointer attribute must be set to point to a valid
+//			large string ME that contains the name (IP address or URI) of the outbound proxy server for SIP
+//			signalling messages. If an outbound SIP proxy is not used, the outbound proxy address pointer
+//			attribute must be set to a null pointer. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Primary Sip Dns
-//			Primary SIP DNS: This attribute specifies the primary SIP DNS IP address. If the value of this
-//			attribute is 0, the primary DNS server is defined in the corresponding IP host config data or
-//			IPv6 host config data ME. If the value is non-zero, it takes precedence over the primary DNS
-//			server defined in the IP host config data or IPv6 host config data ME. (R,-W, set-by-create)
-//			(mandatory) (4-bytes)
+//			This attribute specifies the primary SIP DNS IP address. If the value of this attribute is 0,
+//			the primary DNS server is defined in the corresponding IP host config data or IPv6 host config
+//			data ME. If the value is non-zero, it takes precedence over the primary DNS server defined in
+//			the IP host config data or IPv6 host config data ME. (R,-W, set-by-create) (mandatory) (4-bytes)
 //
 //		Secondary Sip Dns
-//			Secondary SIP DNS: This attribute specifies the secondary SIP DNS IP address. If the value of
-//			this attribute is 0, the secondary DNS server is defined in the corresponding IP host config
-//			data or IPv6 host config data ME. If the value is non-zero, it takes precedence over the
-//			secondary DNS server defined in the IP host config data or IPv6 host config data ME. (R,-W, set-
-//			by-create) (mandatory) (4-bytes)
+//			This attribute specifies the secondary SIP DNS IP address. If the value of this attribute is 0,
+//			the secondary DNS server is defined in the corresponding IP host config data or IPv6 host config
+//			data ME. If the value is non-zero, it takes precedence over the secondary DNS server defined in
+//			the IP host config data or IPv6 host config data ME. (R,-W, set-by-create) (mandatory) (4-bytes)
 //
 //		Tcp_Udp Pointer
 //			TCP/UDP pointer: This pointer associates the SIP agent with the TCP/UDP config data ME to be
@@ -85,53 +81,85 @@
 //			(mandatory) (2-bytes)
 //
 //		Sip Reg Exp Time
-//			SIP reg exp time: This attribute specifies the SIP registration expiration time in seconds. If
-//			its value is 0, the SIP agent does not add an expiration time to the registration requests and
-//			does not perform reregistration. The default value is 3600-s. (R,-W) (mandatory) (4-bytes)
+//			This attribute specifies the SIP registration expiration time in seconds. If its value is 0, the
+//			SIP agent does not add an expiration time to the registration requests and does not perform
+//			reregistration. The default value is 3600-s. (R,-W) (mandatory) (4-bytes)
 //
 //		Sip Rereg Head Start Time
-//			SIP rereg head start time: This attribute specifies the time in seconds prior to timeout that
-//			causes the SIP agent to start the re-registration process. The default value is 360-s. (R,-W)
-//			(mandatory) (4-bytes)
+//			This attribute specifies the time in seconds prior to timeout that causes the SIP agent to start
+//			the re-registration process. The default value is 360-s. (R,-W) (mandatory) (4-bytes)
 //
 //		Host Part Uri
-//			Host part URI: This attribute points to a large string ME that contains the host or domain part
-//			of the SIP address of record for users connected to this ONU. A null pointer indicates that the
-//			current address in the IP host config ME is to be used. (R,-W, setbycreate) (mandatory)
-//			(2-bytes)
+//			This attribute points to a large string ME that contains the host or domain part of the SIP
+//			address of record for users connected to this ONU. A null pointer indicates that the current
+//			address in the IP host config ME is to be used. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Sip Status
+//			5	Failed - Timeout
+//
+//			6	Redundant, offline: this instance of the SIP agent config data occupies the role of a
+//			redundant server, and is not presently in use.
+//
 //			(R) (mandatory) (1-byte)
 //
+//			This attribute shows the current status of the SIP agent. Values are as follows.
+//
+//			0	Ok/initial
+//
+//			1	Connected
+//
+//			2	Failed - ICMP error
+//
+//			3	Failed - Malformed response
+//
+//			4	Failed - Inadequate info response
+//
 //		Sip Registrar
-//			SIP registrar: This attribute points to a network address ME that contains the name (IP address
-//			or resolved name) of the registrar server for SIP signalling messages. Examples: "10.10.10.10"
-//			and "proxy.voip.net". (R,-W, set-by-create) (mandatory) (2-bytes)
+//			This attribute points to a network address ME that contains the name (IP address or resolved
+//			name) of the registrar server for SIP signalling messages. Examples: "10.10.10.10" and
+//			"proxy.voip.net". (R,-W, set-by-create) (mandatory) (2-bytes)
 //
 //		Softswitch
-//			Softswitch:	This attribute identifies the SIP gateway softswitch vendor. The format is four
-//			ASCII coded alphabetic characters [A..Z] as defined in [ATIS0300220]. A value of four null bytes
-//			indicates an unknown or unspecified vendor. (R,-W, setbycreate) (mandatory) (4-bytes)
+//			This attribute identifies the SIP gateway softswitch vendor. The format is four ASCII coded
+//			alphabetic characters [A..Z] as defined in [ATIS0300220]. A value of four null bytes indicates
+//			an unknown or unspecified vendor. (R,-W, setbycreate) (mandatory) (4-bytes)
 //
 //		Sip Response Table
+//			This attribute specifies the tone and text to be presented to the subscriber upon receipt of
+//			various SIP messages (normally 4xx, 5xx, 6xx message codes). The table is a sequence of entries,
+//			each of which is defined as follows.
+//
+//			SIP response code (2 bytes): This field is the value of the SIP message code. It also serves as
+//			the index into the SIP response table. When a set operation is performed with the value 0 in
+//			this field, the table is cleared.
+//
+//			Tone (1 byte): This field specifies one of the tones in the tone pattern table of the associated
+//			voice service profile. The specified tone is played to the subscriber.
+//
+//			Text message (2 bytes): This field is a pointer to a large string that contains a message to be
+//			displayed to the subscriber. If the value of this field is a null pointer, text pre-associated
+//			with the tone may be displayed, or no text at all.
+//
+//			(R, W) (optional) (N * 5 bytes)
+//
 //			NOTE 2 - This model assumes that SIP response tones and text are common to all POTS lines that
 //			share a given SIP agent.
 //
 //		Sip Option Transmit Control
-//			SIP option transmit control: This Boolean attribute specifies that the ONU is (true) or is not
-//			(false) enabled to transmit SIP options. The default value is recommended to be false. (R, W,
-//			setbycreate) (optional) (1 byte)
+//			This Boolean attribute specifies that the ONU is (true) or is not (false) enabled to transmit
+//			SIP options. The default value is recommended to be false. (R, W, setbycreate) (optional) (1
+//			byte)
 //
 //		Sip Uri Format
-//			SIP URI format: This attribute specifies the format of the URI in outgoing SIP messages. The
-//			recommended default value 0 specifies TEL URIs; the value 1 specifies SIP URIs. Other values are
-//			reserved. (R, W, setbycreate) (optional) (1 byte)
+//			This attribute specifies the format of the URI in outgoing SIP messages. The recommended default
+//			value 0 specifies TEL URIs; the value 1 specifies SIP URIs. Other values are reserved. (R, W,
+//			setbycreate) (optional) (1 byte)
 //
 //		Redundant Sip Agent Pointer
-//			Redundant SIP agent pointer: This attribute points to another SIP agent config data ME, which is
-//			understood to provide redundancy. The initial SIP agent is determined by the pointer from the
-//			SIP user data ME. It is the manager's responsibility to provision a group of redundant SIP
-//			agents with mutually consistent attributes. (R, W, setbycreate) (optional) (2 bytes)
+//			This attribute points to another SIP agent config data ME, which is understood to provide
+//			redundancy. The initial SIP agent is determined by the pointer from the SIP user data ME. It is
+//			the manager's responsibility to provision a group of redundant SIP agents with mutually
+//			consistent attributes. (R, W, setbycreate) (optional) (2 bytes)
 //
 type SipAgentConfigData struct {
 	ManagedEntityDefinition
diff --git a/generated/sipagentconfigdata2.go b/generated/sipagentconfigdata2.go
new file mode 100644
index 0000000..1ed14a8
--- /dev/null
+++ b/generated/sipagentconfigdata2.go
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+/*
+ * NOTE: This file was generated, manual edits will be overwritten!
+ *
+ * Generated by 'goCodeGenerator.py':
+ *              https://github.com/cboling/OMCI-parser/README.md
+ */
+
+package generated
+
+import "github.com/deckarep/golang-set"
+
+// SipAgentConfigData2ClassID is the 16-bit ID for the OMCI
+// Managed entity SIP agent config data 2
+const SipAgentConfigData2ClassID = ClassID(407) // 0x0197
+
+var sipagentconfigdata2BME *ManagedEntityDefinition
+
+// SipAgentConfigData2 (Class ID: #407 / 0x0197)
+//	This ME supplements SIP agent config data ME. Instances of this ME are created and deleted by
+//	the OLT.
+//
+//	Relationships
+//		An instance of this ME is associated with a SIP agent config data.
+//
+//	Attributes
+//		Managed Entity Id
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the corresponding SIP agent config data.  Note that this
+//			entity is associated with the primary SIP agent config data (if SIP agent is involved in
+//			protection). (R, set-by-create) (mandatory) (2-bytes)
+//
+//		In_Use_Options_Timer
+//			In-Use-Options-Timer: This attribute defines the frequency that a SIP options packet is sent to
+//			the SIP proxy in-use. When a SIP options packet is not responded to by the SIP proxy, it is
+//			marked as unavailable. Otherwise, it is marked as available. Units are seconds. The default
+//			value 0 specifies vendor-specific implementation. (R, W, set-by-create) (mandatory) (2-byte)
+//
+//		Alternate_Options_Timer
+//			Alternate-Options-Timer: This attribute defines the frequency that a SIP options packet is sent
+//			to the standby SIP proxy. When a SIP options packet is not responded to by the standby SIP
+//			proxy, it is marked as unavailable. Otherwise, it is marked as available. Units are seconds. The
+//			default value 0 specifies vendor-specific implementation. (R, W, set-by-create) (mandatory)
+//			(2-byte)
+//
+//		Revertive
+//			This Boolean attribute specifies whether the SIP UA is involved in revertive (true) or non-
+//			revertive (false) switching. The default value is recommended to be false. (R, W, set-by-create)
+//			(mandatory) (1 byte)
+//
+//		Current Proxy Server Resolved Address
+//			This attribute contains the resolved IP address of the in-use SIP proxy. If the value is
+//			0.0.x.y, where x and y are not both 0, then x.y is to be interpreted as a pointer to a large
+//			string ME that represents an IPv6 address. Otherwise, the address is an IPv4 address (R)
+//			(optional) (4-bytes)
+//
+//		Current Proxy Server Resolved Name
+//			This attribute contains a pointer to the large string ME that contains the resolved name of the
+//			SIP proxy in-use. (R) (optional) (2-bytes)
+//
+//		Alternate Proxy Server Resolved Address
+//			This attribute contains the resolved IP address of the alternate SIP proxy. If the value is
+//			0.0.x.y, where x and y are not both 0, then x.y is to be interpreted as a pointer to a large
+//			string ME that represents an IPv6 address. Otherwise, the address is an IPv4 address (R)
+//			(optional) (4-bytes)
+//
+//		Alternate Proxy Server Resolved Name
+//			This attribute contains a pointer to the large string ME that contains the resolved name of the
+//			alternate SIP proxy. (R) (optional) (2-bytes)
+//
+type SipAgentConfigData2 struct {
+	ManagedEntityDefinition
+	Attributes AttributeValueMap
+}
+
+func init() {
+	sipagentconfigdata2BME = &ManagedEntityDefinition{
+		Name:    "SipAgentConfigData2",
+		ClassID: 407,
+		MessageTypes: mapset.NewSetWith(
+			Create,
+			Delete,
+			Get,
+			Set,
+			GetCurrentData,
+		),
+		AllowedAttributeMask: 0xfe00,
+		AttributeDefinitions: AttributeDefinitionMap{
+			0: Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read, SetByCreate), false, false, false, 0),
+			1: Uint16Field("InUseOptionsTimer", UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 1),
+			2: Uint16Field("AlternateOptionsTimer", UnsignedIntegerAttributeType, 0x4000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 2),
+			3: ByteField("Revertive", UnsignedIntegerAttributeType, 0x2000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 3),
+			4: Uint32Field("CurrentProxyServerResolvedAddress", UnsignedIntegerAttributeType, 0x1000, 0, mapset.NewSetWith(Read), false, true, false, 4),
+			5: Uint16Field("CurrentProxyServerResolvedName", UnsignedIntegerAttributeType, 0x0800, 0, mapset.NewSetWith(Read), false, true, false, 5),
+			6: Uint32Field("AlternateProxyServerResolvedAddress", UnsignedIntegerAttributeType, 0x0400, 0, mapset.NewSetWith(Read), false, true, false, 6),
+			7: Uint16Field("AlternateProxyServerResolvedName", UnsignedIntegerAttributeType, 0x0200, 0, mapset.NewSetWith(Read), false, true, false, 7),
+		},
+		Access:  CreatedByOlt,
+		Support: UnknownSupport,
+	}
+}
+
+// NewSipAgentConfigData2 (class ID 407) creates the basic
+// Managed Entity definition that is used to validate an ME of this type that
+// is received from or transmitted to the OMCC.
+func NewSipAgentConfigData2(params ...ParamData) (*ManagedEntity, OmciErrors) {
+	return NewManagedEntity(*sipagentconfigdata2BME, params...)
+}
diff --git a/generated/sipagentperformancemonitoringhistorydata.go b/generated/sipagentperformancemonitoringhistorydata.go
index a201006..66850e2 100644
--- a/generated/sipagentperformancemonitoringhistorydata.go
+++ b/generated/sipagentperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // SipAgentPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity SIP agent performance monitoring history data
-const SipAgentPerformanceMonitoringHistoryDataClassID ClassID = ClassID(151)
+const SipAgentPerformanceMonitoringHistoryDataClassID = ClassID(151) // 0x0097
 
 var sipagentperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// SipAgentPerformanceMonitoringHistoryData (class ID #151)
+// SipAgentPerformanceMonitoringHistoryData (Class ID: #151 / 0x0097)
 //	This ME collects PM data for the associated VoIP SIP agent. Instances of this ME are created and
 //	deleted by the OLT.
 //
@@ -42,15 +42,14 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the corresponding SIP agent config
-//			data or to the SIP config portal. If a non-OMCI configuration method is used for VoIP, there can
-//			be only one live ME instance, associated with the SIP config portal, and with ME ID 0. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the corresponding SIP agent config data or to the SIP config
+//			portal. If a non-OMCI configuration method is used for VoIP, there can be only one live ME
+//			instance, associated with the SIP config portal, and with ME ID 0. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -58,54 +57,48 @@
 //			data 2 ME is optional. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Transactions
-//			Transactions: This attribute counts the number of new transactions that were initiated. (R)
-//			(optional) (4-bytes)
-//
-//		Rx Invite Reqs
-//			Rx invite reqs: This attribute counts received invite messages, including retransmissions. (R)
-//			(optional) (4-bytes)
-//
-//		Rx Invite Retrans
-//			Rx invite retrans: This attribute counts received invite retransmission messages. (R) (optional)
+//			This attribute counts the number of new transactions that were initiated. (R) (optional)
 //			(4-bytes)
 //
+//		Rx Invite Reqs
+//			This attribute counts received invite messages, including retransmissions. (R) (optional)
+//			(4-bytes)
+//
+//		Rx Invite Retrans
+//			This attribute counts received invite retransmission messages. (R) (optional) (4-bytes)
+//
 //		Rx Noninvite Reqs
-//			Rx noninvite reqs: This attribute counts received non-invite messages, including
-//			retransmissions. (R) (optional) (4-bytes)
+//			This attribute counts received non-invite messages, including retransmissions. (R) (optional)
+//			(4-bytes)
 //
 //		Rx Noninvite Retrans
-//			Rx noninvite retrans: This attribute counts received non-invite retransmission messages. (R)
-//			(optional) (4-bytes)
+//			This attribute counts received non-invite retransmission messages. (R) (optional) (4-bytes)
 //
 //		Rx Response
-//			Rx response:	This attribute counts total responses received. (R) (optional) (4-bytes)
+//			This attribute counts total responses received. (R) (optional) (4-bytes)
 //
 //		Rx Response Retransmissions
-//			Rx response retransmissions: This attribute counts total response retransmissions received. (R)
-//			(optional) (4-bytes)
+//			This attribute counts total response retransmissions received. (R) (optional) (4-bytes)
 //
 //		Tx Invite Reqs
-//			Tx invite reqs: This attribute counts transmitted invite messages, including retransmissions.
-//			(R) (optional) (4-bytes)
+//			This attribute counts transmitted invite messages, including retransmissions. (R) (optional)
+//			(4-bytes)
 //
 //		Tx Invite Retrans
-//			Tx invite retrans: This attribute counts transmitted invite retransmission messages. (R)
-//			(optional) (4-bytes)
+//			This attribute counts transmitted invite retransmission messages. (R) (optional) (4-bytes)
 //
 //		Tx Noninvite Reqs
-//			Tx noninvite reqs: This attribute counts transmitted non-invite messages, including
-//			retransmissions. (R) (optional) (4-bytes)
+//			This attribute counts transmitted non-invite messages, including retransmissions. (R) (optional)
+//			(4-bytes)
 //
 //		Tx Noninvite Retrans
-//			Tx noninvite retrans: This attribute counts transmitted non-invite retransmission messages. (R)
-//			(optional) (4-bytes)
+//			This attribute counts transmitted non-invite retransmission messages. (R) (optional) (4-bytes)
 //
 //		Tx Response
-//			Tx response: This attribute counts the total responses sent. (R) (optional) (4-bytes)
+//			This attribute counts the total responses sent. (R) (optional) (4-bytes)
 //
 //		Tx Response Retransmissions
-//			Tx response retransmissions: This attribute counts total response retransmissions sent. (R)
-//			(optional) (4-bytes)
+//			This attribute counts total response retransmissions sent. (R) (optional) (4-bytes)
 //
 type SipAgentPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/sipcallinitiationperformancemonitoringhistorydata.go b/generated/sipcallinitiationperformancemonitoringhistorydata.go
index 5a46091..23949a5 100644
--- a/generated/sipcallinitiationperformancemonitoringhistorydata.go
+++ b/generated/sipcallinitiationperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // SipCallInitiationPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity SIP call initiation performance monitoring history data
-const SipCallInitiationPerformanceMonitoringHistoryDataClassID ClassID = ClassID(152)
+const SipCallInitiationPerformanceMonitoringHistoryDataClassID = ClassID(152) // 0x0098
 
 var sipcallinitiationperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// SipCallInitiationPerformanceMonitoringHistoryData (class ID #152)
+// SipCallInitiationPerformanceMonitoringHistoryData (Class ID: #152 / 0x0098)
 //	This ME collects PM data related to call initiations of a VoIP SIP agent. Instances of this ME
 //	are created and deleted by the OLT.
 //
@@ -43,15 +43,13 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the SIP agent config data or the
-//			SIP config portal ME. If a nonOMCI configuration method is used for VoIP, there can be only one
-//			live ME instance, associated with the SIP config portal, and with ME ID 0. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the SIP agent config data or the SIP config portal ME. If a
+//			nonOMCI configuration method is used for VoIP, there can be only one live ME instance,
+//			associated with the SIP config portal, and with ME ID 0. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -59,24 +57,24 @@
 //			data 2 ME is optional. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Failed To Connect Counter
-//			Failed to connect counter: This attribute counts the number of times that the SIP UA failed to
-//			reach/connect its TCP/UDP peer during SIP call initiations. (R) (mandatory) (4-bytes)
+//			This attribute counts the number of times that the SIP UA failed to reach/connect its TCP/UDP
+//			peer during SIP call initiations. (R) (mandatory) (4-bytes)
 //
 //		Failed To Validate Counter
-//			Failed to validate counter: This attribute counts the number of times that the SIP UA failed to
-//			validate its peer during SIP call initiations. (R) (mandatory) (4-bytes)
-//
-//		Timeout Counter
-//			Timeout counter: This attribute counts the number of times that the SIP UA timed out during SIP
+//			This attribute counts the number of times that the SIP UA failed to validate its peer during SIP
 //			call initiations. (R) (mandatory) (4-bytes)
 //
+//		Timeout Counter
+//			This attribute counts the number of times that the SIP UA timed out during SIP call initiations.
+//			(R) (mandatory) (4-bytes)
+//
 //		Failure Received Counter
-//			Failure received counter: This attribute counts the number of times that the SIP UA received a
-//			failure error code during SIP call initiations. (R) (mandatory) (4-bytes)
+//			This attribute counts the number of times that the SIP UA received a failure error code during
+//			SIP call initiations. (R) (mandatory) (4-bytes)
 //
 //		Failed To Authenticate Counter
-//			Failed to authenticate counter: This attribute counts the number of times that the SIP UA failed
-//			to authenticate itself during SIP call initiations. (R) (mandatory) (4-bytes)
+//			This attribute counts the number of times that the SIP UA failed to authenticate itself during
+//			SIP call initiations. (R) (mandatory) (4-bytes)
 //
 type SipCallInitiationPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/sipconfigportal.go b/generated/sipconfigportal.go
new file mode 100644
index 0000000..7f525c0
--- /dev/null
+++ b/generated/sipconfigportal.go
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+/*
+ * NOTE: This file was generated, manual edits will be overwritten!
+ *
+ * Generated by 'goCodeGenerator.py':
+ *              https://github.com/cboling/OMCI-parser/README.md
+ */
+
+package generated
+
+import "github.com/deckarep/golang-set"
+
+// SipConfigPortalClassID is the 16-bit ID for the OMCI
+// Managed entity SIP config portal
+const SipConfigPortalClassID = ClassID(149) // 0x0095
+
+var sipconfigportalBME *ManagedEntityDefinition
+
+// SipConfigPortal (Class ID: #149 / 0x0095)
+//	The SIP config portal ME provides a way for the OLT to discover the configuration text delivered
+//	to an ONU by a non-OMCI SIP VoIP configuration method ([BBF TR-069], sipping framework, etc.).
+//	Text retrieved from this ME is not required to be understood by the OLT or EMS, but it may be
+//	useful for human or vendor-specific analysis tools. See also the MGC config portal ME.
+//
+//	An instance of this ME may be created by an ONU that supports non-OMCI SIP configuration. It is
+//	not reported during an MIB upload.
+//
+//	Relationships
+//		One instance of this ME is associated with the ONU.
+//
+//	Attributes
+//		Managed Entity Id
+//			This attribute uniquely identifies each instance of this ME. There is one instance, number 0.
+//			(R) (mandatory) (2-bytes)
+//
+//		Configuration Text Table
+//			This attribute is used to pass a textual representation of the VoIP configuration back to the
+//			OLT. The contents are vendor-specific. The get, get next sequence must be used with this
+//			attribute since its size is unspecified. Upon ME instantiation, the ONU sets this attribute to
+//			0. (R) (mandatory) (x-bytes)
+//
+type SipConfigPortal struct {
+	ManagedEntityDefinition
+	Attributes AttributeValueMap
+}
+
+func init() {
+	sipconfigportalBME = &ManagedEntityDefinition{
+		Name:    "SipConfigPortal",
+		ClassID: 149,
+		MessageTypes: mapset.NewSetWith(
+			Get,
+			GetNext,
+		),
+		AllowedAttributeMask: 0x8000,
+		AttributeDefinitions: AttributeDefinitionMap{
+			0: Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read), false, false, false, 0),
+			1: TableField("ConfigurationTextTable", TableAttributeType, 0x8000, TableInfo{nil, 25}, mapset.NewSetWith(Read), true, false, false, 1),
+		},
+		Access:  CreatedByOnu,
+		Support: UnknownSupport,
+	}
+}
+
+// NewSipConfigPortal (class ID 149) creates the basic
+// Managed Entity definition that is used to validate an ME of this type that
+// is received from or transmitted to the OMCC.
+func NewSipConfigPortal(params ...ParamData) (*ManagedEntity, OmciErrors) {
+	return NewManagedEntity(*sipconfigportalBME, params...)
+}
diff --git a/generated/sipuserdata.go b/generated/sipuserdata.go
index fe7bbab..dcbe99e 100644
--- a/generated/sipuserdata.go
+++ b/generated/sipuserdata.go
@@ -27,11 +27,11 @@
 
 // SipUserDataClassID is the 16-bit ID for the OMCI
 // Managed entity SIP user data
-const SipUserDataClassID ClassID = ClassID(153)
+const SipUserDataClassID = ClassID(153) // 0x0099
 
 var sipuserdataBME *ManagedEntityDefinition
 
-// SipUserData (class ID #153)
+// SipUserData (Class ID: #153 / 0x0099)
 //	The SIP user data defines the user specific configuration attributes associated with a specific
 //	VoIP CTP. This entity is conditionally required for ONUs that offer VoIP SIP services. If a non-
 //	OMCI interface is used to manage SIP for VoIP, this ME is unnecessary. The non-OMCI interface
@@ -45,61 +45,59 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Sip Agent Pointer
-//			SIP agent pointer: This attribute points to the SIP agent config data ME to be used for
-//			signalling. (R,-W, setbycreate) (mandatory) (2-bytes)
-//
-//		User Part Aor
-//			User part AOR: This attribute points to a large string that contains the user identification
-//			part of the address of record. This can take the form of an alphanumeric string or the
-//			subscriber's directory number. A null pointer indicates the absence of an AOR. (R,-W,
+//			This attribute points to the SIP agent config data ME to be used for signalling. (R,-W,
 //			setbycreate) (mandatory) (2-bytes)
 //
+//		User Part Aor
+//			This attribute points to a large string that contains the user identification part of the
+//			address of record. This can take the form of an alphanumeric string or the subscriber's
+//			directory number. A null pointer indicates the absence of an AOR. (R,-W, setbycreate)
+//			(mandatory) (2-bytes)
+//
 //		Sip Display Name
-//			SIP display name: This ASCII string attribute defines the customer ID used for the display
-//			attribute in outgoing SIP messages. The default value is null (all zero bytes) (R,-W)
-//			(mandatory) (25-bytes)
+//			This ASCII string attribute defines the customer ID used for the display attribute in outgoing
+//			SIP messages. The default value is null (all zero bytes) (R,-W) (mandatory) (25-bytes)
 //
 //		Username And Password
-//			Username and password: This attribute points to an authentication security method ME that
-//			contains the SIP user name and password used for authentication. A null pointer indicates no
-//			username and password. (R,-W, setbycreate) (mandatory) (2)
+//			This attribute points to an authentication security method ME that contains the SIP user name
+//			and password used for authentication. A null pointer indicates no username and password. (R,-W,
+//			setbycreate) (mandatory) (2)
 //
 //		Voicemail Server Sip Uri
-//			Voicemail server SIP URI: This attribute points to a network address ME that contains the name
-//			(IP address or URI) of the SIP voicemail server for SIP signalling messages. A null pointer
-//			indicates the absence of a SIP voicemail server. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute points to a network address ME that contains the name (IP address or URI) of the
+//			SIP voicemail server for SIP signalling messages. A null pointer indicates the absence of a SIP
+//			voicemail server. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Voicemail Subscription Expiration Time
-//			Voicemail subscription expiration time: This attribute defines the voicemail subscription
-//			expiration time in seconds. If this value is 0, the SIP agent uses an implementation-specific
-//			value. This attribute is recommended to be set to 3600-s by default. (R,-W, setbycreate)
-//			(mandatory) (4-bytes)
+//			This attribute defines the voicemail subscription expiration time in seconds. If this value is
+//			0, the SIP agent uses an implementation-specific value. This attribute is recommended to be set
+//			to 3600-s by default. (R,-W, setbycreate) (mandatory) (4-bytes)
 //
 //		Network Dial Plan Pointer
-//			Network dial plan pointer: This attribute points to a network dial plan table. A null pointer
-//			indicates the absence of a network dial plan. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute points to a network dial plan table. A null pointer indicates the absence of a
+//			network dial plan. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Application Services Profile Pointer
-//			Application services profile pointer: This attribute points to a VoIP application services
-//			profile. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute points to a VoIP application services profile. (R,-W, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Feature Code Pointer
-//			Feature code pointer: This attribute points to the VoIP feature access codes ME for this
-//			subscriber. A null pointer indicates the absence of a VoIP feature access codes ME. (R,-W, set-
-//			by-create) (mandatory) (2-bytes)
+//			This attribute points to the VoIP feature access codes ME for this subscriber. A null pointer
+//			indicates the absence of a VoIP feature access codes ME. (R,-W, set-by-create) (mandatory)
+//			(2-bytes)
 //
 //		Pptp Pointer
-//			PPTP pointer: This attribute points to the PPTP POTS UNI ME that provides the analogue telephony
-//			adaptor (ATA) function. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute points to the PPTP POTS UNI ME that provides the analogue telephony adaptor (ATA)
+//			function. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Release Timer
-//			Release timer: This attribute contains a release timer defined in seconds. The value 0 specifies
-//			that the ONU is to use its internal default. The default value of this attribute is 10-s. (R,-W)
-//			(optional) (1-byte)
+//			This attribute contains a release timer defined in seconds. The value 0 specifies that the ONU
+//			is to use its internal default. The default value of this attribute is 10-s. (R,-W) (optional)
+//			(1-byte)
 //
 //		Receiver Off Hook Roh Timer
 //			Receiver off hook (ROH) timer:	This attribute defines the time in seconds for the ROH condition
diff --git a/generated/snmpconfigurationdata.go b/generated/snmpconfigurationdata.go
index 1c878ad..2e6c9e4 100644
--- a/generated/snmpconfigurationdata.go
+++ b/generated/snmpconfigurationdata.go
@@ -27,11 +27,11 @@
 
 // SnmpConfigurationDataClassID is the 16-bit ID for the OMCI
 // Managed entity SNMP configuration data
-const SnmpConfigurationDataClassID ClassID = ClassID(335)
+const SnmpConfigurationDataClassID = ClassID(335) // 0x014f
 
 var snmpconfigurationdataBME *ManagedEntityDefinition
 
-// SnmpConfigurationData (class ID #335)
+// SnmpConfigurationData (Class ID: #335 / 0x014f)
 //	The SNMP configuration data ME provides a way for the OLT to provision an IP path for an SNMP
 //	management agent.
 //
@@ -42,41 +42,40 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The ME IDs 0 and
-//			0xFFFF are reserved. (R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. The ME IDs 0 and 0xFFFF are
+//			reserved. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Snmp Version
-//			SNMP version: This integer attribute is the SNMP protocol version to be supported. (R,-W,
-//			setbycreate) (mandatory) (2-bytes)
+//			This integer attribute is the SNMP protocol version to be supported. (R,-W, setbycreate)
+//			(mandatory) (2-bytes)
 //
 //		Snmp Agent Address
-//			SNMP agent address: This attribute is a pointer to a TCP/UDP config data ME, which provides the
-//			SNMP agent. (R, W, setbycreate) (mandatory) (2 bytes)
+//			This attribute is a pointer to a TCP/UDP config data ME, which provides the SNMP agent. (R, W,
+//			setbycreate) (mandatory) (2 bytes)
 //
 //		Snmp Server Address
-//			SNMP server address: This attribute is the IP address of the SNMP server. (R, W, setbycreate)
-//			(mandatory) (4 bytes)
+//			This attribute is the IP address of the SNMP server. (R, W, setbycreate) (mandatory) (4 bytes)
 //
 //		Snmp Server Port
-//			SNMP server port: This attribute is the UDP port number of the SNMP server. (R, W, setbycreate)
-//			(mandatory) (2 bytes)
+//			This attribute is the UDP port number of the SNMP server. (R, W, setbycreate) (mandatory) (2
+//			bytes)
 //
 //		Security Name Pointer
-//			Security name pointer: This attribute points to a large string whose content represents the SNMP
-//			security name in a human-readable format that is independent of the security model. SecurityName
-//			is defined in [b-IETF RFC 2571]. (R, W, setbycreate) (mandatory) (2 bytes)
+//			This attribute points to a large string whose content represents the SNMP security name in a
+//			human-readable format that is independent of the security model. SecurityName is defined in
+//			[b-IETF RFC 2571]. (R, W, setbycreate) (mandatory) (2 bytes)
 //
 //		Community For Read
-//			Community for read: This attribute is a pointer to a large string that contains the name of the
-//			read community. (R, W, setbycreate) (mandatory) (2 bytes)
+//			This attribute is a pointer to a large string that contains the name of the read community. (R,
+//			W, setbycreate) (mandatory) (2 bytes)
 //
 //		Community For Write
-//			Community for write: This attribute is a pointer to a large string that contains the name of the
-//			write community. (R, W, setbycreate) (mandatory) (2 bytes)
+//			This attribute is a pointer to a large string that contains the name of the write community. (R,
+//			W, setbycreate) (mandatory) (2 bytes)
 //
 //		Sys Name Pointer
-//			Sys name pointer: This attribute points to a large string whose content identifies the SNMP
-//			system name. SysName is defined in [b-IETF RFC-3418]. (R, W, setbycreate) (mandatory) (2 bytes)
+//			This attribute points to a large string whose content identifies the SNMP system name. SysName
+//			is defined in [b-IETF RFC-3418]. (R, W, setbycreate) (mandatory) (2 bytes)
 //
 type SnmpConfigurationData struct {
 	ManagedEntityDefinition
diff --git a/generated/softwareimage.go b/generated/softwareimage.go
index 27efb8f..b900d0b 100644
--- a/generated/softwareimage.go
+++ b/generated/softwareimage.go
@@ -14,6 +14,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+/*
+ * NOTE: This file was generated, manual edits will be overwritten!
+ *
+ * Generated by 'goCodeGenerator.py':
+ *              https://github.com/cboling/OMCI-parser/README.md
+ */
 
 package generated
 
@@ -21,11 +27,11 @@
 
 // SoftwareImageClassID is the 16-bit ID for the OMCI
 // Managed entity Software image
-const SoftwareImageClassID ClassID = ClassID(7)
+const SoftwareImageClassID = ClassID(7) // 0x0007
 
 var softwareimageBME *ManagedEntityDefinition
 
-// SoftwareImage (class ID #7)
+// SoftwareImage (Class ID: #7 / 0x0007)
 //	This ME models an executable software image stored in the ONU (documented here as its
 //	fundamental usage). It may also be used to represent an opaque vendor-specific file
 //	(vendorspecific usage).
@@ -56,49 +62,48 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The first byte
-//			indicates the physical location of the equipment hosting the software image, either the ONU (0)
-//			or a cardholder (1..254). The second byte distinguishes between the two software image ME
-//			instances (0..1). (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. The first byte indicates the
+//			physical location of the equipment hosting the software image, either the ONU (0) or a
+//			cardholder (1..254). The second byte distinguishes between the two software image ME instances
+//			(0..1). (R) (mandatory) (2-bytes)
 //
 //		Version
-//			Version:	This string attribute identifies the version of the software. (R) (mandatory)
-//			(14-bytes)
+//			This string attribute identifies the version of the software. (R) (mandatory) (14-bytes)
 //
 //		Is Committed
-//			Is committed: This attribute indicates whether the associated software image is committed (1) or
-//			uncommitted (0). By definition, the committed software image is loaded and executed upon reboot
-//			of the ONU or circuit pack. During normal operation, one software image is always committed,
-//			while the other is uncommitted. Under no circumstances are both software images allowed to be
-//			committed at the same time. On the other hand, both software images could be uncommitted at the
-//			same time if both were invalid. Upon ME instantiation, instance 0 is initialized to committed,
-//			while instance 1 is initialized to uncommitted (i.e., the ONU ships from the factory with image
-//			0 committed). (R) (mandatory) (1-byte)
+//			This attribute indicates whether the associated software image is committed (1) or uncommitted
+//			(0). By definition, the committed software image is loaded and executed upon reboot of the ONU
+//			or circuit pack. During normal operation, one software image is always committed, while the
+//			other is uncommitted. Under no circumstances are both software images allowed to be committed at
+//			the same time. On the other hand, both software images could be uncommitted at the same time if
+//			both were invalid. Upon ME instantiation, instance 0 is initialized to committed, while instance
+//			1 is initialized to uncommitted (i.e., the ONU ships from the factory with image 0 committed).
+//			(R) (mandatory) (1-byte)
 //
 //		Is Active
-//			Is active:	This attribute indicates whether the associated software image is active (1) or
-//			inactive (0). By definition, the active software image is one that is currently loaded and
-//			executing in the ONU or circuit pack. Under normal operation, one software image is always
-//			active while the other is inactive. Under no circumstances are both software images allowed to
-//			be active at the same time. On the other hand, both software images could be inactive at the
-//			same time if both were invalid. (R) (mandatory) (1-byte)
+//			This attribute indicates whether the associated software image is active (1) or inactive (0). By
+//			definition, the active software image is one that is currently loaded and executing in the ONU
+//			or circuit pack. Under normal operation, one software image is always active while the other is
+//			inactive. Under no circumstances are both software images allowed to be active at the same time.
+//			On the other hand, both software images could be inactive at the same time if both were invalid.
+//			(R) (mandatory) (1-byte)
 //
 //		Is Valid
-//			Is valid:	This attribute indicates whether the associated software image is valid (1) or invalid
-//			(0). By definition, a software image is valid if it has been verified to be an executable code
-//			image. The verification mechanism is not subject to standardization; however, it should include
-//			at least a data integrity check [e.g., a cyclic redundancy check (CRC)] of the entire code
-//			image. Upon ME instantiation or software download completion, the ONU validates the associated
-//			code image and sets this attribute according to the result. (R) (mandatory) (1-byte)
+//			This attribute indicates whether the associated software image is valid (1) or invalid (0). By
+//			definition, a software image is valid if it has been verified to be an executable code image.
+//			The verification mechanism is not subject to standardization; however, it should include at
+//			least a data integrity check [e.g., a cyclic redundancy check (CRC)] of the entire code image.
+//			Upon ME instantiation or software download completion, the ONU validates the associated code
+//			image and sets this attribute according to the result. (R) (mandatory) (1-byte)
 //
 //		Product Code
-//			Product code:	This attribute provides a way for a vendor to indicate product code information on
-//			a file. It is a character string, padded with trailing nulls if it is shorter than 25 bytes. (R)
-//			(optional) (25 bytes)
+//			This attribute provides a way for a vendor to indicate product code information on a file. It is
+//			a character string, padded with trailing nulls if it is shorter than 25 bytes. (R) (optional)
+//			(25 bytes)
 //
 //		Image Hash
-//			Image hash:	This attribute is an MD5 hash of the software image. It is computed at completion of
-//			the end download action. (R) (optional) (16-bytes)
+//			This attribute is an MD5 hash of the software image. It is computed at completion of the end
+//			download action. (R) (optional) (16-bytes)
 //
 type SoftwareImage struct {
 	ManagedEntityDefinition
diff --git a/generated/t-cont.go b/generated/t-cont.go
index 01af10c..7fe59c9 100644
--- a/generated/t-cont.go
+++ b/generated/t-cont.go
@@ -27,11 +27,11 @@
 
 // TContClassID is the 16-bit ID for the OMCI
 // Managed entity T-CONT
-const TContClassID ClassID = ClassID(262)
+const TContClassID = ClassID(262) // 0x0106
 
 var tcontBME *ManagedEntityDefinition
 
-// TCont (class ID #262)
+// TCont (Class ID: #262 / 0x0106)
 //	An instance of the traffic container ME T-CONT represents a logical connection group associated
 //	with a G-PON PLOAM layer alloc-ID. A T-CONT can accommodate GEM packets in priority queues or
 //	traffic schedulers that exist in the GEM layer.
@@ -58,11 +58,11 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. This 2-byte
-//			number indicates the physical capability that realizes the TCONT. It may be represented as
-//			0xSSBB, where SS indicates the slot ID that contains this T-CONT (0 for the ONU as a whole), and
-//			BB is the TCONT ID, numbered by the ONU itself. T-CONTs are numbered in ascending order, with
-//			the range 0..255 in each slot. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. This 2-byte number indicates the
+//			physical capability that realizes the TCONT. It may be represented as 0xSSBB, where SS indicates
+//			the slot ID that contains this T-CONT (0 for the ONU as a whole), and BB is the TCONT ID,
+//			numbered by the ONU itself. T-CONTs are numbered in ascending order, with the range 0..255 in
+//			each slot. (R) (mandatory) (2-bytes)
 //
 //		Alloc_Id
 //			Alloc-ID:	This attribute links the T-CONT with the alloc-ID assigned by the OLT in the
@@ -73,10 +73,20 @@
 //			(mandatory) (2-bytes)
 //
 //		Deprecated
-//			Deprecated:	The ONU should set this attribute to the value 1, and the OLT should ignore it. (R)
-//			(mandatory) (1-byte)
+//			The ONU should set this attribute to the value 1, and the OLT should ignore it. (R) (mandatory)
+//			(1-byte)
 //
 //		Policy
+//			This attribute indicates the T-CONT's traffic scheduling policy. Valid values:
+//
+//			0	Null
+//
+//			1	Strict priority
+//
+//			2	WRR - Weighted round robin
+//
+//			(R, W) (mandatory) (1 byte)
+//
 //			NOTE - This attribute is read-only, unless otherwise specified by the QoS configuration
 //			flexibility attribute of the ONU2-G ME. If flexible configuration is not supported, the ONU
 //			should reject an attempt to set it with a parameter error result-reason code.
diff --git a/generated/tcadaptorperformancemonitoringhistorydataxdsl.go b/generated/tcadaptorperformancemonitoringhistorydataxdsl.go
index 1b9dcf1..8c13139 100644
--- a/generated/tcadaptorperformancemonitoringhistorydataxdsl.go
+++ b/generated/tcadaptorperformancemonitoringhistorydataxdsl.go
@@ -27,11 +27,11 @@
 
 // TcAdaptorPerformanceMonitoringHistoryDataXdslClassID is the 16-bit ID for the OMCI
 // Managed entity TC adaptor performance monitoring history data xDSL
-const TcAdaptorPerformanceMonitoringHistoryDataXdslClassID ClassID = ClassID(116)
+const TcAdaptorPerformanceMonitoringHistoryDataXdslClassID = ClassID(116) // 0x0074
 
 var tcadaptorperformancemonitoringhistorydataxdslBME *ManagedEntityDefinition
 
-// TcAdaptorPerformanceMonitoringHistoryDataXdsl (class ID #116)
+// TcAdaptorPerformanceMonitoringHistoryDataXdsl (Class ID: #116 / 0x0074)
 //	This ME collects PM data of an xTUC to xTUR ATM data path. Instances of this ME are created and
 //	deleted by the OLT.
 //
@@ -42,13 +42,11 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID:	This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP xDSL UNI part 1. (R)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP xDSL UNI part 1. (R) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data1/2 ID: This attribute points to an instance of the threshold data1 ME that
diff --git a/generated/tcpudpconfigdata.go b/generated/tcpudpconfigdata.go
index 87a8192..df11642 100644
--- a/generated/tcpudpconfigdata.go
+++ b/generated/tcpudpconfigdata.go
@@ -27,11 +27,11 @@
 
 // TcpUdpConfigDataClassID is the 16-bit ID for the OMCI
 // Managed entity TCP/UDP config data
-const TcpUdpConfigDataClassID ClassID = ClassID(136)
+const TcpUdpConfigDataClassID = ClassID(136) // 0x0088
 
 var tcpudpconfigdataBME *ManagedEntityDefinition
 
-// TcpUdpConfigData (class ID #136)
+// TcpUdpConfigData (Class ID: #136 / 0x0088)
 //	The TCP/UDP config data ME configures services based on the transmission control protocol (TCP)
 //	and user datagram protocol (UDP) that are offered from an IP host. If a non-OMCI interface is
 //	used to manage an IP service, this ME is unnecessary; the non-OMCI interface supplies the
@@ -45,17 +45,16 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. It is
-//			recommended that the ME ID be the same as the port number. (R, setbycreate) (mandatory)
-//			(2-bytes)
+//			This attribute uniquely identifies each instance of this ME. It is recommended that the ME ID be
+//			the same as the port number. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Port Id
-//			Port ID:	This attribute specifies the port number that offers the TCP/UDP service. (R,-W,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute specifies the port number that offers the TCP/UDP service. (R,-W, setbycreate)
+//			(mandatory) (2-bytes)
 //
 //		Protocol
-//			Protocol:	This attribute specifies the protocol type as defined by [b-IANA] (protocol numbers),
-//			for example UDP (0x11). (R,-W, setbycreate) (mandatory) (1-byte)
+//			This attribute specifies the protocol type as defined by [b-IANA] (protocol numbers), for
+//			example UDP (0x11). (R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Tos_Diffserv Field
 //			TOS/diffserv field: This attribute specifies the value of the TOS/diffserv field of the IPv4
@@ -64,9 +63,9 @@
 //			points). (R,-W, set-by-create) (mandatory) (1-byte)
 //
 //		Ip Host Pointer
-//			IP host pointer: This attribute points to the IP host config data or IPv6 host config data ME
-//			associated with this TCP/UDP data. Any number of ports and protocols may be associated with an
-//			IP host. (R, W, set-by-create) (mandatory) (2 bytes)
+//			This attribute points to the IP host config data or IPv6 host config data ME associated with
+//			this TCP/UDP data. Any number of ports and protocols may be associated with an IP host. (R, W,
+//			set-by-create) (mandatory) (2 bytes)
 //
 type TcpUdpConfigData struct {
 	ManagedEntityDefinition
diff --git a/generated/tcpudpperformancemonitoringhistorydata.go b/generated/tcpudpperformancemonitoringhistorydata.go
index 5914ebd..fd7073b 100644
--- a/generated/tcpudpperformancemonitoringhistorydata.go
+++ b/generated/tcpudpperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // TcpUdpPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity TCP/UDP performance monitoring history data
-const TcpUdpPerformanceMonitoringHistoryDataClassID ClassID = ClassID(342)
+const TcpUdpPerformanceMonitoringHistoryDataClassID = ClassID(342) // 0x0156
 
 var tcpudpperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// TcpUdpPerformanceMonitoringHistoryData (class ID #342)
+// TcpUdpPerformanceMonitoringHistoryData (Class ID: #342 / 0x0156)
 //	This ME collects PM data related to a TCP or UDP port. Instances of this ME are created and
 //	deleted by the OLT.
 //
@@ -42,13 +42,12 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the TCP/UDP config data ME. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the TCP/UDP config data ME. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -56,24 +55,24 @@
 //			data 2 ME is optional. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Socket Failed
-//			Socket failed:	This attribute is incremented when an attempt to create a socket associated with
-//			a port fails. (R) (mandatory) (2-bytes)
-//
-//		Listen Failed
-//			Listen failed:	This attribute is incremented when an attempt by a service to listen for a
-//			request on a port fails. (R) (mandatory) (2-bytes)
-//
-//		Bind Failed
-//			Bind failed:	This attribute is incremented when an attempt by a service to bind to a port fails.
+//			This attribute is incremented when an attempt to create a socket associated with a port fails.
 //			(R) (mandatory) (2-bytes)
 //
-//		Accept Failed
-//			Accept failed: This attribute is incremented when an attempt to accept a connection on a port
+//		Listen Failed
+//			This attribute is incremented when an attempt by a service to listen for a request on a port
 //			fails. (R) (mandatory) (2-bytes)
 //
+//		Bind Failed
+//			This attribute is incremented when an attempt by a service to bind to a port fails. (R)
+//			(mandatory) (2-bytes)
+//
+//		Accept Failed
+//			This attribute is incremented when an attempt to accept a connection on a port fails. (R)
+//			(mandatory) (2-bytes)
+//
 //		Select Failed
-//			Select failed:	This attribute is incremented when an attempt to perform a select on a group of
-//			ports fails. (R) (mandatory) (2-bytes)
+//			This attribute is incremented when an attempt to perform a select on a group of ports fails. (R)
+//			(mandatory) (2-bytes)
 //
 type TcpUdpPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/thresholddata1.go b/generated/thresholddata1.go
index 2d062ee..d398f61 100644
--- a/generated/thresholddata1.go
+++ b/generated/thresholddata1.go
@@ -27,11 +27,11 @@
 
 // ThresholdData1ClassID is the 16-bit ID for the OMCI
 // Managed entity Threshold data 1
-const ThresholdData1ClassID ClassID = ClassID(273)
+const ThresholdData1ClassID = ClassID(273) // 0x0111
 
 var thresholddata1BME *ManagedEntityDefinition
 
-// ThresholdData1 (class ID #273)
+// ThresholdData1 (Class ID: #273 / 0x0111)
 //	Threshold data are partitioned into two MEs for historical reasons. An instance of this ME,
 //	together with an optional instance of the threshold data 2 ME, contains threshold values for
 //	counters in PM history data MEs.
@@ -46,8 +46,12 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
+//			(2-bytes)
+//
+//			The following seven attributes specify threshold values for seven thresholded counters in
+//			associated PM history data MEs. The definition of each PM history ME includes a table that links
+//			each thresholded counter to one of these threshold value attributes.
 //
 //		Threshold Value_1
 //			Threshold value-1: (R,-W, setbycreate) (mandatory) (4-bytes)
diff --git a/generated/thresholddata2.go b/generated/thresholddata2.go
index 8145d76..3cd0975 100644
--- a/generated/thresholddata2.go
+++ b/generated/thresholddata2.go
@@ -27,11 +27,11 @@
 
 // ThresholdData2ClassID is the 16-bit ID for the OMCI
 // Managed entity Threshold data 2
-const ThresholdData2ClassID ClassID = ClassID(274)
+const ThresholdData2ClassID = ClassID(274) // 0x0112
 
 var thresholddata2BME *ManagedEntityDefinition
 
-// ThresholdData2 (class ID #274)
+// ThresholdData2 (Class ID: #274 / 0x0112)
 //	Together with an instance of the threshold data 1 ME, an instance of this ME contains threshold
 //	values for counters maintained in one or more instances of PM history data MEs.
 //
@@ -44,8 +44,12 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Its value is the
-//			same as that of the paired threshold data-1-instance. (R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Its value is the same as that of
+//			the paired threshold data-1-instance. (R, setbycreate) (mandatory) (2-bytes)
+//
+//			The following seven attributes specify threshold values for seven thresholded counters in
+//			associated PM history data MEs. The definition of each PM history ME includes a table that links
+//			each thresholded counter to one of these threshold value attributes.
 //
 //		Threshold Value_8
 //			Threshold value-8: (R,-W, setbycreate) (mandatory) (4-bytes)
diff --git a/generated/timestatusmessage.go b/generated/timestatusmessage.go
new file mode 100644
index 0000000..d227b91
--- /dev/null
+++ b/generated/timestatusmessage.go
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+/*
+ * NOTE: This file was generated, manual edits will be overwritten!
+ *
+ * Generated by 'goCodeGenerator.py':
+ *              https://github.com/cboling/OMCI-parser/README.md
+ */
+
+package generated
+
+import "github.com/deckarep/golang-set"
+
+// TimeStatusMessageClassID is the 16-bit ID for the OMCI
+// Managed entity Time Status Message
+const TimeStatusMessageClassID = ClassID(440) // 0x01b8
+
+var timestatusmessageBME *ManagedEntityDefinition
+
+// TimeStatusMessage (Class ID: #440 / 0x01b8)
+//	This ME provides status and characterization information for the time-transmitting node and its
+//	grandmaster. An ONU that supports time synchronization automatically creates an instance of this
+//	ME. The best practise is to set all the attributes at the same time.
+//
+//	Relationships
+//		The single instance of this ME is associated with the ONU ME.
+//
+//	Attributes
+//		Managed Entity Id
+//			This attribute uniquely identifies each instance of this ME. There is only one instance, number
+//			0. (R) (mandatory) (2 bytes)
+//
+//		Domain Number
+//			Using the format of clause 7.1 of [IEEE 1588]. The default value is 0. (R, W) (mandatory) (1
+//			byte)
+//
+//		Flag Field
+//			The field format is given in the table. Value 1 represents "true". (R, W) (mandatory) (1 byte)
+//
+//		Currentutcoffset
+//			Provides the UTC offset value between the TAI and UTC timescales (UTC Offset-= TAI-- UTC), as
+//			specified in clause 7.2.3 of [IEEE 1588]. (R, W) (mandatory) (2 bytes)
+//
+//		Priority1
+//			As specified in clause 7.6.2.2 of [IEEE 1588]. (R, W) (mandatory) (1 byte)
+//
+//		Clockclass
+//			Provides the clockClass information denoting the traceability of the time distributed by the
+//			grandmaster clock, as specified in clause 7.6.2.4 of [IEEE 1588]. (R, W) (mandatory) (1 byte)
+//
+//		Accuracy
+//			Indicates the expected accuracy of a clock when it is the grandmaster, as specified in clause
+//			7.6.2.5 of [IEEE 1588]. (R, W) (mandatory) (1 byte)
+//
+//		Offsetscaledlogvariance
+//			Provides the estimate of the time variance, as specified in clause-7.6.3 of [IEEE 1588]. (R, W)
+//			(mandatory) (2 bytes)
+//
+//		Priority2
+//			As specified in clause 7.6.2.3 of [IEEE 1588]. (R, W) (mandatory) (1 byte)
+//
+//			Grandmaster ID: The clockIdentity attribute of the grandmaster, taken from the IEEE EUI64
+//			individual assigned numbers. (R, W) (mandatory) (8 bytes)
+//
+//			Steps removed:	Provides the number of boundary clocks between the local clock and the master.
+//			(R, W) (mandatory) (2 bytes)
+//
+//			Time source:	Indicates the source of time used by the grandmaster clock, as specified in clause
+//			7.6.2.6 of [IEEE 1588]. (R, W) (mandatory) (1 byte)
+//
+type TimeStatusMessage struct {
+	ManagedEntityDefinition
+	Attributes AttributeValueMap
+}
+
+func init() {
+	timestatusmessageBME = &ManagedEntityDefinition{
+		Name:    "TimeStatusMessage",
+		ClassID: 440,
+		MessageTypes: mapset.NewSetWith(
+			Get,
+			Set,
+		),
+		AllowedAttributeMask: 0xff00,
+		AttributeDefinitions: AttributeDefinitionMap{
+			0: Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read), false, false, false, 0),
+			1: ByteField("DomainNumber", UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read, Write), false, false, false, 1),
+			2: ByteField("FlagField", UnsignedIntegerAttributeType, 0x4000, 0, mapset.NewSetWith(Read, Write), false, false, false, 2),
+			3: Uint16Field("Currentutcoffset", UnsignedIntegerAttributeType, 0x2000, 0, mapset.NewSetWith(Read, Write), false, false, false, 3),
+			4: ByteField("Priority1", UnsignedIntegerAttributeType, 0x1000, 0, mapset.NewSetWith(Read, Write), false, false, false, 4),
+			5: ByteField("Clockclass", UnsignedIntegerAttributeType, 0x0800, 0, mapset.NewSetWith(Read, Write), false, false, false, 5),
+			6: ByteField("Accuracy", UnsignedIntegerAttributeType, 0x0400, 0, mapset.NewSetWith(Read, Write), false, false, false, 6),
+			7: Uint16Field("Offsetscaledlogvariance", UnsignedIntegerAttributeType, 0x0200, 0, mapset.NewSetWith(Read, Write), false, false, false, 7),
+			8: ByteField("Priority2", UnsignedIntegerAttributeType, 0x0100, 0, mapset.NewSetWith(Read, Write), false, false, false, 8),
+		},
+		Access:  CreatedByOnu,
+		Support: UnknownSupport,
+		Alarms: AlarmMap{
+			0: "Clock unlock",
+			1: "ESMC loss",
+			2: "Time unlock",
+		},
+	}
+}
+
+// NewTimeStatusMessage (class ID 440) creates the basic
+// Managed Entity definition that is used to validate an ME of this type that
+// is received from or transmitted to the OMCC.
+func NewTimeStatusMessage(params ...ParamData) (*ManagedEntity, OmciErrors) {
+	return NewManagedEntity(*timestatusmessageBME, params...)
+}
diff --git a/generated/trafficdescriptor.go b/generated/trafficdescriptor.go
index 1bac10e..cf1ccc0 100644
--- a/generated/trafficdescriptor.go
+++ b/generated/trafficdescriptor.go
@@ -27,11 +27,11 @@
 
 // TrafficDescriptorClassID is the 16-bit ID for the OMCI
 // Managed entity Traffic descriptor
-const TrafficDescriptorClassID ClassID = ClassID(280)
+const TrafficDescriptorClassID = ClassID(280) // 0x0118
 
 var trafficdescriptorBME *ManagedEntityDefinition
 
-// TrafficDescriptor (class ID #280)
+// TrafficDescriptor (Class ID: #280 / 0x0118)
 //	The traffic descriptor is a profile that allows for traffic management. A priority controlled
 //	ONU can point from a MAC bridge port configuration data ME to a traffic descriptor in order to
 //	implement traffic management (marking, policing). A rate controlled ONU can point to a traffic
@@ -61,35 +61,93 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Cir
-//			CIR:	This attribute specifies the committed information rate, in bytes per second. The default
-//			is 0. (R,-W, setbycreate) (optional) (4-bytes)
+//			This attribute specifies the committed information rate, in bytes per second. The default is 0.
+//			(R,-W, setbycreate) (optional) (4-bytes)
 //
 //		Pir
-//			PIR:	This attribute specifies the peak information rate, in bytes per second. The default value
-//			0 accepts the ONU's factory policy. (R,-W, setbycreate) (optional) (4-bytes)
+//			This attribute specifies the peak information rate, in bytes per second. The default value 0
+//			accepts the ONU's factory policy. (R,-W, setbycreate) (optional) (4-bytes)
 //
 //		Cbs
-//			CBS:	This attribute specifies the committed burst size, in bytes. The default is 0. (R,-W,
+//			This attribute specifies the committed burst size, in bytes. The default is 0. (R,-W,
 //			setbycreate) (optional) (4-bytes)
 //
 //		Pbs
-//			PBS:	This attribute specifies the peak burst size, in bytes. The default value 0 accepts the
-//			ONU's factory policy. (R,-W, setbycreate) (optional) (4-bytes)
+//			This attribute specifies the peak burst size, in bytes. The default value 0 accepts the ONU's
+//			factory policy. (R,-W, setbycreate) (optional) (4-bytes)
 //
 //		Colour Mode
+//			This attribute specifies whether the colour marking algorithm considers pre-existing marking on
+//			ingress packets (colour-aware) or ignores it (colour-blind). In colour-aware mode, packets can
+//			only be demoted (from green to yellow or red, or from yellow to red). The default value is 0.
+//
+//			0	Colour-blind
+//
+//			1	Colour-aware
+//
 //			(R,-W, setbycreate) (optional) (1-byte)
 //
 //		Ingress Colour Marking
+//			This attribute is meaningful in colour-aware mode. It identifies how pre-existing drop
+//			precedence is marked on ingress packets. For DEI and PCP marking, a drop eligible indicator is
+//			equivalent to yellow; otherwise, the colour is green. For DSCP AF marking, the lowest drop
+//			precedence is equivalent to green; otherwise, the colour is yellow. The default value is 0.
+//
+//			0	No marking (ignore ingress marking)
+//
+//			2	DEI [IEEE 802.1ad]
+//
+//			3	PCP 8P0D [IEEE 802.1ad]
+//
+//			4	PCP 7P1D [IEEE 802.1ad]
+//
+//			5	PCP 6P2D [IEEE 802.1ad]
+//
+//			6	PCP 5P3D [IEEE 802.1ad]
+//
+//			7	DSCP AF class [IETF RFC 2597]
+//
 //			(R,-W, setbycreate) (optional) (1-byte)
 //
 //		Egress Colour Marking
+//			2	DEI [IEEE 802.1ad]
+//
+//			3	PCP 8P0D [IEEE 802.1ad]
+//
+//			4	PCP 7P1D [IEEE 802.1ad]
+//
+//			5	PCP 6P2D [IEEE 802.1ad]
+//
+//			6	PCP 5P3D [IEEE 802.1ad]
+//
+//			7	DSCP AF class [IETF RFC 2597]
+//
 //			(R,-W, setbycreate) (optional) (1-byte)
 //
+//			This attribute specifies how drop precedence is to be marked by the ONU on egress packets. If
+//			set to internal marking only, the externally visible packet contents are not modified, but the
+//			packet is identified in a vendor-specific local way that indicates its colour to the priority
+//			queue ME. It is possible for the egress marking to differ from the ingress marking; for example,
+//			ingress PCP marking could be translated to DEI egress marking. The default value is 0.
+//
+//			0	No marking
+//
+//			1	Internal marking only
+//
 //		Meter Type
+//			This attribute specifies the algorithm used to determine the colour of the packet. The default
+//			value is 0.
+//
+//			0	Not specified
+//
+//			1	[b-IETF RFC 4115]
+//
+//			2	[b-IETF RFC 2698]
+//
 //			(R, setbycreate) (optional) (1-byte)
 //
 type TrafficDescriptor struct {
diff --git a/generated/trafficscheduler.go b/generated/trafficscheduler.go
index 0996420..6be642f 100644
--- a/generated/trafficscheduler.go
+++ b/generated/trafficscheduler.go
@@ -27,11 +27,11 @@
 
 // TrafficSchedulerClassID is the 16-bit ID for the OMCI
 // Managed entity Traffic scheduler
-const TrafficSchedulerClassID ClassID = ClassID(278)
+const TrafficSchedulerClassID = ClassID(278) // 0x0116
 
 var trafficschedulerBME *ManagedEntityDefinition
 
-// TrafficScheduler (class ID #278)
+// TrafficScheduler (Class ID: #278 / 0x0116)
 //	NOTE 1 - In [ITU-T G.984.4], this ME is called a traffic scheduler-G.
 //
 //	An instance of this ME represents a logical object that can control upstream GEM packets. A
@@ -50,31 +50,57 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. This 2-byte
-//			number indicates the physical capability that realizes the traffic scheduler. The first byte is
-//			the slot ID of the circuit pack with which this traffic scheduler is associated. For a traffic
-//			scheduler that is not associated with a circuit pack, the first byte is 0xFF. The second byte is
-//			the traffic scheduler id, assigned by the ONU itself. Traffic schedulers are numbered in
-//			ascending order with the range 0..0xFF in each circuit pack or in the ONU core. (R) (mandatory)
-//			(2-bytes)
+//			This attribute uniquely identifies each instance of this ME. This 2-byte number indicates the
+//			physical capability that realizes the traffic scheduler. The first byte is the slot ID of the
+//			circuit pack with which this traffic scheduler is associated. For a traffic scheduler that is
+//			not associated with a circuit pack, the first byte is 0xFF. The second byte is the traffic
+//			scheduler id, assigned by the ONU itself. Traffic schedulers are numbered in ascending order
+//			with the range 0..0xFF in each circuit pack or in the ONU core. (R) (mandatory) (2-bytes)
 //
 //		T_Cont Pointer
+//			T-CONT pointer: This attribute points to the T-CONT ME instance associated with this traffic
+//			scheduler. This pointer is used when this traffic scheduler is connected to the T-CONT directly;
+//			It is null (0) otherwise. (R, W) (mandatory) (2 bytes)
+//
 //			NOTE 2 - This attribute is read-only unless otherwise specified by the QoS configuration
 //			flexibility attribute of the ONU2-G ME. If flexible configuration is not supported, the ONU
 //			should reject an attempt to set the TCONT pointer attribute with a parameter error result-reason
 //			code.
 //
 //		Traffic Scheduler Pointer
-//			Traffic scheduler pointer: This attribute points to another traffic scheduler ME instance that
-//			may serve this traffic scheduler. This pointer is used when this traffic scheduler is connected
-//			to another traffic scheduler; it is null (0) otherwise. (R) (mandatory) (2-bytes)
+//			This attribute points to another traffic scheduler ME instance that may serve this traffic
+//			scheduler. This pointer is used when this traffic scheduler is connected to another traffic
+//			scheduler; it is null (0) otherwise. (R) (mandatory) (2-bytes)
 //
 //		Policy
+//			This attribute represents scheduling policy. Valid values include:
+//
+//			0	Null
+//
+//			1	Strict priority
+//
+//			2	WRR (weighted round robin)
+//
+//			The traffic scheduler derives priority or weight values for its tributary traffic schedulers or
+//			priority queues from the tributary MEs themselves.
+//
+//			(R, W) (mandatory) (1 byte)
+//
 //			NOTE 3 - This attribute is read-only unless otherwise specified by the QoS configuration
 //			flexibility attribute of the ONU2-G ME. If flexible configuration is not supported, the ONU
 //			should reject an attempt to set the policy attribute with a parameter error result-reason code.
 //
 //		Priority_Weight
+//			Priority/weight: This attribute represents the priority for strict priority scheduling or the
+//			weight for WRR scheduling. This value is used by the next upstream ME, as indicated by the
+//			T-CONT pointer attribute or traffic scheduler pointer attribute.
+//
+//			If the indicated pointer has policy-=-strict priority, this value is interpreted as a priority
+//			(0 is the highest priority, 255 the lowest).
+//
+//			If the indicated pointer has policy-=-WRR, this value is interpreted as a weight. Higher values
+//			receive more bandwidth.
+//
 //			Upon ME instantiation, the ONU sets this attribute to 0. (R,-W) (mandatory) (1-byte)
 //
 type TrafficScheduler struct {
diff --git a/generated/twdmchannelmanagedentity.go b/generated/twdmchannelmanagedentity.go
index 78547a8..b0b0ce5 100644
--- a/generated/twdmchannelmanagedentity.go
+++ b/generated/twdmchannelmanagedentity.go
@@ -27,11 +27,11 @@
 
 // TwdmChannelManagedEntityClassID is the 16-bit ID for the OMCI
 // Managed entity TWDM channel managed entity
-const TwdmChannelManagedEntityClassID ClassID = ClassID(443)
+const TwdmChannelManagedEntityClassID = ClassID(443) // 0x01bb
 
 var twdmchannelmanagedentityBME *ManagedEntityDefinition
 
-// TwdmChannelManagedEntity (class ID #443)
+// TwdmChannelManagedEntity (Class ID: #443 / 0x01bb)
 //	This ME provides an anchor for the MEs involved in collection of PM statistics per TWDM channel,
 //	as stipulated by clause 14 of [ITU-T-G.989.3]. Instances of this ME are instantiated
 //	autonomously by the ONU.
@@ -43,31 +43,29 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. This 2-byte
-//			number is represented as 0xSSBB, where SS indicates the ONU slot ID, and BB is the TWDM channel
-//			ME number assigned by the ONU itself, starting from 0 in the ascending order. (R) (mandatory)
-//			(2-bytes)
+//			This attribute uniquely identifies each instance of this ME. This 2-byte number is represented
+//			as 0xSSBB, where SS indicates the ONU slot ID, and BB is the TWDM channel ME number assigned by
+//			the ONU itself, starting from 0 in the ascending order. (R) (mandatory) (2-bytes)
 //
 //		Active Channel Indication
-//			Active channel indication: The default value is false. The ONU sets the attribute to true when
-//			it receives the Channel_Profile PLOAM messages for that channel. The ONU clears the attribute
-//			when it receives the Channel_Profile PLOAM message marked ``void'' for that channel. (R)
-//			(mandatory) (1-byte)
+//			The default value is false. The ONU sets the attribute to true when it receives the
+//			Channel_Profile PLOAM messages for that channel. The ONU clears the attribute when it receives
+//			the Channel_Profile PLOAM message marked ``void'' for that channel. (R) (mandatory) (1-byte)
 //
 //		Operational Channel Indication
-//			Operational channel indication: A Boolean attribute that is set to true for an active TWDM
-//			channel in which the ONT is currently operating. The operational statistic is accumulated in the
-//			PM history data MEs associated with that TWDM channel. (R) (mandatory) (1-byte)
+//			A Boolean attribute that is set to true for an active TWDM channel in which the ONT is currently
+//			operating. The operational statistic is accumulated in the PM history data MEs associated with
+//			that TWDM channel. (R) (mandatory) (1-byte)
 //
 //		Downstream Wavelength Channel
-//			Downstream wavelength channel: For an active TWDM channel, this attribute identifies the
-//			downstream wavelength channel in reference to Table 11-2 of [ITU-T-G.989.2]. For an inactive
-//			channel it has value 0xFF. (R) (mandatory) (1-byte)
+//			For an active TWDM channel, this attribute identifies the downstream wavelength channel in
+//			reference to Table 11-2 of [ITU-T-G.989.2]. For an inactive channel it has value 0xFF. (R)
+//			(mandatory) (1-byte)
 //
 //		Upstream Wavelength Channel
-//			Upstream wavelength channel: For an active TWDM channel, this attribute identifies the upstream
-//			wavelength channel in reference to Table VIII-5 of [ITU-T-G.989.2]. For an inactive channel its
-//			value of 0xFF. (R) (mandatory) (1-byte)
+//			For an active TWDM channel, this attribute identifies the upstream wavelength channel in
+//			reference to Table VIII-5 of [ITU-T-G.989.2]. For an inactive channel its value of 0xFF. (R)
+//			(mandatory) (1-byte)
 //
 type TwdmChannelManagedEntity struct {
 	ManagedEntityDefinition
diff --git a/generated/twdmchannelomciperformancemonitoringhistorydata.go b/generated/twdmchannelomciperformancemonitoringhistorydata.go
index 11c60f0..fb1f97d 100644
--- a/generated/twdmchannelomciperformancemonitoringhistorydata.go
+++ b/generated/twdmchannelomciperformancemonitoringhistorydata.go
@@ -27,15 +27,15 @@
 
 // TwdmChannelOmciPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity TWDM channel OMCI performance monitoring history data
-const TwdmChannelOmciPerformanceMonitoringHistoryDataClassID ClassID = ClassID(452)
+const TwdmChannelOmciPerformanceMonitoringHistoryDataClassID = ClassID(452) // 0x01c4
 
 var twdmchannelomciperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// TwdmChannelOmciPerformanceMonitoringHistoryData (class ID #452)
+// TwdmChannelOmciPerformanceMonitoringHistoryData (Class ID: #452 / 0x01c4)
 //	This ME collects OMCI-related PM data associated with the slot/circuit pack, hosting one or more
 //	ANI-G MEs, for a specific TWDM channel. Instances of this ME are created and deleted by the OLT.
 //
-//	The counters maintained by this ME are characterized as optional in Clause 14 of [ITU-
+//	The counters maintained by this ME are characterized as optional in clause 14 of [ITU-
 //	T-G.989.3].
 //
 //	For a complete discussion of generic PM architecture, refer to clause I.4.
@@ -45,29 +45,24 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the TWDM channel ME. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the TWDM channel ME. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 and 2 MEs
 //			that contains PM threshold values. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Omci Baseline Message Count
-//			OMCI baseline message count: The counter of baseline format OMCI messages directed to the given
-//			ONU. (R) (mandatory) (4-byte)
+//			The counter of baseline format OMCI messages directed to the given ONU. (R) (mandatory) (4-byte)
 //
 //		Omci Extended Message Count
-//			OMCI extended message count: The counter of extended format OMCI messages directed to the given
-//			ONU. (R) (mandatory) (4-byte)
+//			The counter of extended format OMCI messages directed to the given ONU. (R) (mandatory) (4-byte)
 //
 //		Omci Mic Error Count
-//			OMCI MIC error count: The counter of OMCI messages received with MIC errors. (R) (mandatory)
-//			(4-byte)
+//			The counter of OMCI messages received with MIC errors. (R) (mandatory) (4-byte)
 //
 type TwdmChannelOmciPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
@@ -82,8 +77,8 @@
 			Create,
 			Delete,
 			Get,
-			GetCurrentData,
 			Set,
+			GetCurrentData,
 		),
 		AllowedAttributeMask: 0xf800,
 		AttributeDefinitions: AttributeDefinitionMap{
@@ -96,6 +91,9 @@
 		},
 		Access:  CreatedByOlt,
 		Support: UnknownSupport,
+		Alarms: AlarmMap{
+			0: "OMCI MIC error count",
+		},
 	}
 }
 
diff --git a/generated/twdmchannelphylodsperformancemonitoringhistorydata.go b/generated/twdmchannelphylodsperformancemonitoringhistorydata.go
index db46818..93fa9d0 100644
--- a/generated/twdmchannelphylodsperformancemonitoringhistorydata.go
+++ b/generated/twdmchannelphylodsperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // TwdmChannelPhyLodsPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity TWDM channel PHY/LODS performance monitoring history data
-const TwdmChannelPhyLodsPerformanceMonitoringHistoryDataClassID ClassID = ClassID(444)
+const TwdmChannelPhyLodsPerformanceMonitoringHistoryDataClassID = ClassID(444) // 0x01bc
 
 var twdmchannelphylodsperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// TwdmChannelPhyLodsPerformanceMonitoringHistoryData (class ID #444)
+// TwdmChannelPhyLodsPerformanceMonitoringHistoryData (Class ID: #444 / 0x01bc)
 //	This ME collects certain PM data associated with the slot/circuit pack, hosting one or more
 //	ANI-G MEs, and a specific TWDM channel. Instances of this ME are created and deleted by the OLT.
 //
@@ -42,19 +42,17 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the TWDM channel ME. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the TWDM channel ME. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 and 2 MEs
 //			that contains PM threshold values. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
-//		Total Received Words Protected By Bit_Interleaved Parity _32 Bip_32
+//		Total Received Words Protected By Bit_Interleaved Parity_32 Bip_32
 //			Total received words protected by bit-interleaved parity-32 (BIP-32): The count of 4-byte words
 //			included in BIP-32 check. This is a product of the number of downstream FS frames received by
 //			the size of the downstream FS frame after the FEC parity byte, if any, have been removed. The
@@ -68,57 +66,51 @@
 //			removed. (R) (mandatory) (4-bytes)
 //
 //		Corrected Psbd Hec Error Count
-//			Corrected PSBd HEC error count: The count of the errors in either CFC or OCS fields of the PSBd
-//			block that have been corrected using the HEC technique. (R) (mandatory) (4-bytes)
+//			The count of the errors in either CFC or OCS fields of the PSBd block that have been corrected
+//			using the HEC technique. (R) (mandatory) (4-bytes)
 //
 //		Uncorrectable Psbd Hec Error Count
-//			Uncorrectable PSBd HEC error count: The count of the errors in either CFC or OCS fields of the
-//			PSBd block that could not be corrected using the HEC technique. (R) (mandatory) (4-bytes)
+//			The count of the errors in either CFC or OCS fields of the PSBd block that could not be
+//			corrected using the HEC technique. (R) (mandatory) (4-bytes)
 //
 //		Corrected Downstream Fs Header Hec Error Count
-//			Corrected downstream FS header HEC error count: The count of the errors in the downstream FS
-//			header that have been corrected using the HEC technique. (R) (mandatory) (4-bytes)
+//			The count of the errors in the downstream FS header that have been corrected using the HEC
+//			technique. (R) (mandatory) (4-bytes)
 //
 //		Uncorrectable Downstream Fs Header Hec Error Count
-//			Uncorrectable downstream FS header HEC error count: The count of the errors in the downstream FS
-//			header that could not be corrected using the HEC technique. (R) (mandatory) (4-bytes)
+//			The count of the errors in the downstream FS header that could not be corrected using the HEC
+//			technique. (R) (mandatory) (4-bytes)
 //
 //		Total Number Of Lods Events
-//			Total number of LODS events: The count of the state transitions from O5.1/O5.2 to O6, referring
-//			to the ONU activation cycle state machine, clause 12 of [ITU-T-G.989.3]. (R) (mandatory)
-//			(4-bytes)
+//			The count of the state transitions from O5.1/O5.2 to O6, referring to the ONU activation cycle
+//			state machine, clause 12 of [ITU-T-G.989.3]. (R) (mandatory) (4-bytes)
 //
 //		Lods Events Restored In Operating Twdm Channel
-//			LODS events restored in operating TWDM channel: The count of LODS events cleared automatically
-//			without retuning. (R) (mandatory) (4-bytes)
+//			The count of LODS events cleared automatically without retuning. (R) (mandatory) (4-bytes)
 //
 //		Lods Events Restored In Protection Twdm Channel
-//			LODS events restored in protection TWDM channel: The count of LODS events resolved by retuning
-//			to a pre-configured protection TWDM channel. The event is counted against the original operating
-//			channel. (R) (mandatory) (4-bytes)
+//			The count of LODS events resolved by retuning to a pre-configured protection TWDM channel. The
+//			event is counted against the original operating channel. (R) (mandatory) (4-bytes)
 //
 //		Lods Events Restored In Discretionary Twdm Channel
-//			LODS events restored in discretionary TWDM channel: The count of LODS events resolved by
-//			retuning to a TWDM channel chosen by the ONU, without retuning. Implies that the wavelength
-//			channel protection for the operating channel is not active. The event is counted against the
-//			original operating channel (R) (mandatory) (4-bytes)
+//			The count of LODS events resolved by retuning to a TWDM channel chosen by the ONU, without
+//			retuning. Implies that the wavelength channel protection for the operating channel is not
+//			active. The event is counted against the original operating channel (R) (mandatory) (4-bytes)
 //
 //		Lods Events Resulting In Reactivation
-//			LODS events resulting in reactivation: The count of LODS events resolved through ONU
-//			reactivation; that is, either TO2 (without WLCP) or TO3-+ TO4 (with WLCP) expires before the
-//			downstream channel is reacquired, referring to the ONU activation cycle state machine, clause 12
-//			of [ITU-T-G.989.3]. The event is counted against the original operating channel (R) (mandatory)
-//			(4-bytes)
+//			The count of LODS events resolved through ONU reactivation; that is, either TO2 (without WLCP)
+//			or TO3-+ TO4 (with WLCP) expires before the downstream channel is reacquired, referring to the
+//			ONU activation cycle state machine, clause 12 of [ITU-T-G.989.3]. The event is counted against
+//			the original operating channel (R) (mandatory) (4-bytes)
 //
 //		Lods Events Resulting In Reactivation After Retuning To Protection Twdm Channel
-//			LODS events resulting in reactivation after retuning to protection TWDM channel: The count of
-//			LODS events resolved through ONU reactivation after attempted protection switching, which turns
-//			unsuccessful due to a handshake failure. (R) (mandatory) (4-bytes)
+//			The count of LODS events resolved through ONU reactivation after attempted protection switching,
+//			which turns unsuccessful due to a handshake failure. (R) (mandatory) (4-bytes)
 //
 //		Lods Events Resulting In Reactivation After Retuning To Discretionary Twdm Channel
-//			LODS events resulting in reactivation after retuning to discretionary TWDM channel: The count of
-//			LODS events resolved through ONU reactivation after attempted retuning to a discretionary
-//			channel, which turns unsuccessful due to a handshake failure. (R) (mandatory) (4-bytes)
+//			The count of LODS events resolved through ONU reactivation after attempted retuning to a
+//			discretionary channel, which turns unsuccessful due to a handshake failure. (R) (mandatory)
+//			(4-bytes)
 //
 type TwdmChannelPhyLodsPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
@@ -133,8 +125,8 @@
 			Create,
 			Delete,
 			Get,
-			GetCurrentData,
 			Set,
+			GetCurrentData,
 		),
 		AllowedAttributeMask: 0xfffe,
 		AttributeDefinitions: AttributeDefinitionMap{
diff --git a/generated/twdmchannelploamperformancemonitoringhistorydatapart1.go b/generated/twdmchannelploamperformancemonitoringhistorydatapart1.go
index 2633fc5..df4499f 100644
--- a/generated/twdmchannelploamperformancemonitoringhistorydatapart1.go
+++ b/generated/twdmchannelploamperformancemonitoringhistorydatapart1.go
@@ -27,11 +27,11 @@
 
 // TwdmChannelPloamPerformanceMonitoringHistoryDataPart1ClassID is the 16-bit ID for the OMCI
 // Managed entity TWDM channel PLOAM performance monitoring history data part 1
-const TwdmChannelPloamPerformanceMonitoringHistoryDataPart1ClassID ClassID = ClassID(446)
+const TwdmChannelPloamPerformanceMonitoringHistoryDataPart1ClassID = ClassID(446) // 0x01be
 
 var twdmchannelploamperformancemonitoringhistorydatapart1BME *ManagedEntityDefinition
 
-// TwdmChannelPloamPerformanceMonitoringHistoryDataPart1 (class ID #446)
+// TwdmChannelPloamPerformanceMonitoringHistoryDataPart1 (Class ID: #446 / 0x01be)
 //	This ME collects certain PLOAM-related PM data associated with the slot/circuit pack, hosting
 //	one or more ANI-G MEs, for a specific TWDM channel. Instances of this ME are created and deleted
 //	by the OLT.
@@ -55,41 +55,36 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the TWDM channel ME. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the TWDM channel ME. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 and 2 MEs
 //			that contains PM threshold values. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Ploam Mic Errors
-//			PLOAM MIC errors: The counter of received PLOAM messages that remain unparsable due to MIC
-//			error. (R) (mandatory) (4-byte)
-//
-//		Downstream Ploam Message Count
-//			Downstream PLOAM message count: The counter of received broadcast and unicast PLOAM messages
-//			pertaining to the given ONU. (R) (mandatory) (4-byte)
-//
-//		Ranging_Time Message Count
-//			Ranging_Time message count: The counter of received Ranging_Time PLOAM messages. (R) (mandatory)
+//			The counter of received PLOAM messages that remain unparsable due to MIC error. (R) (mandatory)
 //			(4-byte)
 //
-//		Protection_Control Message Count
-//			Protection_Control message count: The counter of received Protection_Control PLOAM messages. (R)
+//		Downstream Ploam Message Count
+//			The counter of received broadcast and unicast PLOAM messages pertaining to the given ONU. (R)
 //			(mandatory) (4-byte)
 //
+//		Ranging_Time Message Count
+//			The counter of received Ranging_Time PLOAM messages. (R) (mandatory) (4-byte)
+//
+//		Protection_Control Message Count
+//			The counter of received Protection_Control PLOAM messages. (R) (mandatory) (4-byte)
+//
 //		Adjust_Tx_Wavelength Message Count
-//			Adjust_Tx_Wavelength message count: The counter of received Adjust_Tx_Wavelength PLOAM messages.
-//			(R) (mandatory) (4-byte)
+//			The counter of received Adjust_Tx_Wavelength PLOAM messages. (R) (mandatory) (4-byte)
 //
 //		Adjust_Tx_Wavelength Adjustment Amplitude
-//			Adjust_Tx_Wavelength adjustment amplitude: An estimator of the absolute value of the
-//			transmission wavelength adjustment. (R) (mandatory) (4-byte)
+//			An estimator of the absolute value of the transmission wavelength adjustment. (R) (mandatory)
+//			(4-byte)
 //
 type TwdmChannelPloamPerformanceMonitoringHistoryDataPart1 struct {
 	ManagedEntityDefinition
@@ -104,8 +99,8 @@
 			Create,
 			Delete,
 			Get,
-			GetCurrentData,
 			Set,
+			GetCurrentData,
 		),
 		AllowedAttributeMask: 0xff00,
 		AttributeDefinitions: AttributeDefinitionMap{
diff --git a/generated/twdmchannelploamperformancemonitoringhistorydatapart2.go b/generated/twdmchannelploamperformancemonitoringhistorydatapart2.go
index 4dfaa75..8aa8f0a 100644
--- a/generated/twdmchannelploamperformancemonitoringhistorydatapart2.go
+++ b/generated/twdmchannelploamperformancemonitoringhistorydatapart2.go
@@ -27,11 +27,11 @@
 
 // TwdmChannelPloamPerformanceMonitoringHistoryDataPart2ClassID is the 16-bit ID for the OMCI
 // Managed entity TWDM channel PLOAM performance monitoring history data part 2
-const TwdmChannelPloamPerformanceMonitoringHistoryDataPart2ClassID ClassID = ClassID(447)
+const TwdmChannelPloamPerformanceMonitoringHistoryDataPart2ClassID = ClassID(447) // 0x01bf
 
 var twdmchannelploamperformancemonitoringhistorydatapart2BME *ManagedEntityDefinition
 
-// TwdmChannelPloamPerformanceMonitoringHistoryDataPart2 (class ID #447)
+// TwdmChannelPloamPerformanceMonitoringHistoryDataPart2 (Class ID: #447 / 0x01bf)
 //	This ME collects additional PLOAM-related PM data associated with the slot/circuit pack, hosting
 //	one or more ANI-G MEs, for a specific TWDM channel. Instances of this ME are created and deleted
 //	by the OLT.
@@ -54,62 +54,52 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the TWDM channel ME. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the TWDM channel ME. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 and 2 MEs
 //			that contains PM threshold values. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		System_Profile Message Count
-//			System_Profile message count: The counter of received System_Profile PLOAM messages. (R)
-//			(mandatory) (4-byte)
+//			The counter of received System_Profile PLOAM messages. (R) (mandatory) (4-byte)
 //
 //		Channel_Profile Message Count
-//			Channel_Profile message count: The counter of received Channel_Profile PLOAM messages. (R)
-//			(mandatory) (4-byte)
+//			The counter of received Channel_Profile PLOAM messages. (R) (mandatory) (4-byte)
 //
 //		Burst_Profile Message Count
-//			Burst_Profile message count: The counter of received Burst_Profile PLOAM messages. (R)
-//			(mandatory) (4-byte)
+//			The counter of received Burst_Profile PLOAM messages. (R) (mandatory) (4-byte)
 //
 //		Assign_Onu_Id Message Count
 //			Assign_ONU-ID message count: The counter of received Assign_ONU-ID PLOAM messages. (R)
 //			(mandatory) (4-byte)
 //
 //		Unsatisfied Adjust_Tx_Wavelength Requests
-//			Unsatisfied Adjust_Tx_Wavelength requests: The counter of Adjust_Tx_Wavelength requests not
-//			applied or partially applied due to target US wavelength being out of Tx tuning range.  (R)
-//			(mandatory) (4-byte)
+//			The counter of Adjust_Tx_Wavelength requests not applied or partially applied due to target US
+//			wavelength being out of Tx tuning range.  (R) (mandatory) (4-byte)
 //
 //		Deactivate_Onu_Id Message Count
 //			Deactivate_ONU-ID message count: The counter of received Deactivate_ONU-ID PLOAM messages. (R)
 //			(mandatory) (4-byte)
 //
 //		Disable_Serial_Number Message Count
-//			Disable_Serial_Number message count: The counter of received Disable_Serial_Number PLOAM
-//			messages. (R) (mandatory) (4-byte)
+//			The counter of received Disable_Serial_Number PLOAM messages. (R) (mandatory) (4-byte)
 //
 //		Request_Registration Message Count
-//			Request_Registration message count: The counter of received Request_Registration PLOAM messages.
-//			(R) (mandatory) (4-byte)
+//			The counter of received Request_Registration PLOAM messages. (R) (mandatory) (4-byte)
 //
 //		Assign_Alloc_Id Message Count
 //			Assign_Alloc-ID message count: The counter of received Assign_Alloc-ID PLOAM messages. (R)
 //			(mandatory) (4-byte)
 //
 //		Key_Control Message Count
-//			Key_Control message count: The counter of received Key_Control PLOAM messages. (R) (mandatory)
-//			(4-byte)
+//			The counter of received Key_Control PLOAM messages. (R) (mandatory) (4-byte)
 //
 //		Sleep_Allow Message Count
-//			Sleep_Allow message count: The counter of received Sleep_Allow PLOAM messages. (R) (mandatory)
-//			(4-byte)
+//			The counter of received Sleep_Allow PLOAM messages. (R) (mandatory) (4-byte)
 //
 //		Tuning_Control_Request Message Count
 //			Tuning_Control/Request message count: The counter of received Tuning_Control PLOAM messages with
@@ -120,8 +110,7 @@
 //			with Complete_d operation code. (R) (mandatory) (4-byte)
 //
 //		Calibration_Request Message Count
-//			Calibration_Request message count: The counter of received Calibration_Request PLOAM messages.
-//			(R) (mandatory) (4-byte)
+//			The counter of received Calibration_Request PLOAM messages. (R) (mandatory) (4-byte)
 //
 type TwdmChannelPloamPerformanceMonitoringHistoryDataPart2 struct {
 	ManagedEntityDefinition
@@ -136,8 +125,8 @@
 			Create,
 			Delete,
 			Get,
-			GetCurrentData,
 			Set,
+			GetCurrentData,
 		),
 		AllowedAttributeMask: 0xffff,
 		AttributeDefinitions: AttributeDefinitionMap{
diff --git a/generated/twdmchannelploamperformancemonitoringhistorydatapart3.go b/generated/twdmchannelploamperformancemonitoringhistorydatapart3.go
index 739dc56..99dbe51 100644
--- a/generated/twdmchannelploamperformancemonitoringhistorydatapart3.go
+++ b/generated/twdmchannelploamperformancemonitoringhistorydatapart3.go
@@ -27,11 +27,11 @@
 
 // TwdmChannelPloamPerformanceMonitoringHistoryDataPart3ClassID is the 16-bit ID for the OMCI
 // Managed entity TWDM channel PLOAM performance monitoring history data part 3
-const TwdmChannelPloamPerformanceMonitoringHistoryDataPart3ClassID ClassID = ClassID(448)
+const TwdmChannelPloamPerformanceMonitoringHistoryDataPart3ClassID = ClassID(448) // 0x01c0
 
 var twdmchannelploamperformancemonitoringhistorydatapart3BME *ManagedEntityDefinition
 
-// TwdmChannelPloamPerformanceMonitoringHistoryDataPart3 (class ID #448)
+// TwdmChannelPloamPerformanceMonitoringHistoryDataPart3 (Class ID: #448 / 0x01c0)
 //	This ME collects remaining PLOAM-related PM data associated with the slot/circuit pack, hosting
 //	one or more ANI-G MEs, for a specific TWDM channel. Instances of this ME are created and deleted
 //	by the OLT.
@@ -46,21 +46,19 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the TWDM channel ME. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the TWDM channel ME. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 and 2 MEs
 //			that contains PM threshold values. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Upstream Ploam Message Count
-//			Upstream PLOAM message count: The aggregate counter of PLOAM messages, other than AK PLOAM MT,
-//			transmitted by the given ONU. (R) (mandatory) (4-byte)
+//			The aggregate counter of PLOAM messages, other than AK PLOAM MT, transmitted by the given ONU.
+//			(R) (mandatory) (4-byte)
 //
 //		Serial_Number_Onu In_Band Message Count
 //			Serial_Number_ONU (in-band) message count: The counter of transmitted in-band Serial_Number_ONU
@@ -71,20 +69,16 @@
 //			control channel (AMCC) Serial_Number_ONU PLOAM messages. (R) (mandatory) (4-byte)
 //
 //		Registration Message Count
-//			Registration message count: The counter of transmitted Registration PLOAM messages. (R)
-//			(mandatory) (4-byte)
+//			The counter of transmitted Registration PLOAM messages. (R) (mandatory) (4-byte)
 //
 //		Key_Report Message Count
-//			Key_Report message count: The counter of transmitted Key_Report PLOAM messages. (R) (mandatory)
-//			(4-byte)
+//			The counter of transmitted Key_Report PLOAM messages. (R) (mandatory) (4-byte)
 //
 //		Acknowledgement Message Count
-//			Acknowledgement message count: The counter of transmitted Registration PLOAM messages. (R)
-//			(mandatory) (4-byte)
+//			The counter of transmitted Registration PLOAM messages. (R) (mandatory) (4-byte)
 //
 //		Sleep_Request Message Count
-//			Sleep_Request message count: The counter of transmitted Sleep_Request PLOAM messages. (R)
-//			(mandatory) (4-byte)
+//			The counter of transmitted Sleep_Request PLOAM messages. (R) (mandatory) (4-byte)
 //
 //		Tuning_Response Ack_Nack Message Count
 //			Tuning_Response (ACK/NACK) message count: The counter of transmitted Tuning_Response PLOAM
@@ -95,13 +89,11 @@
 //			PLOAM messages with Complete_u/Rollback operation code. (R) (mandatory) (4-byte)
 //
 //		Power_Consumption_Report Message Count
-//			Power_Consumption_Report message count: The counter of transmitted Power_Consumption_Report
-//			PLOAM messages. (R) (mandatory) (4-byte)
+//			The counter of transmitted Power_Consumption_Report PLOAM messages. (R) (mandatory) (4-byte)
 //
 //		Change_Power_Level Parameter Error Count
-//			Change_Power_Level parameter error count: The counter of transmitted Acknowledgement PLOAM
-//			messages with Parameter Error completion code in response to Change_Power_Level PLOAM message.
-//			(R) (mandatory) (4-byte)
+//			The counter of transmitted Acknowledgement PLOAM messages with Parameter Error completion code
+//			in response to Change_Power_Level PLOAM message. (R) (mandatory) (4-byte)
 //
 type TwdmChannelPloamPerformanceMonitoringHistoryDataPart3 struct {
 	ManagedEntityDefinition
@@ -116,8 +108,8 @@
 			Create,
 			Delete,
 			Get,
-			GetCurrentData,
 			Set,
+			GetCurrentData,
 		),
 		AllowedAttributeMask: 0xfff8,
 		AttributeDefinitions: AttributeDefinitionMap{
diff --git a/generated/twdmchanneltuningperformancemonitoringhistorydatapart1.go b/generated/twdmchanneltuningperformancemonitoringhistorydatapart1.go
index 292d21f..bc14a28 100644
--- a/generated/twdmchanneltuningperformancemonitoringhistorydatapart1.go
+++ b/generated/twdmchanneltuningperformancemonitoringhistorydatapart1.go
@@ -27,11 +27,11 @@
 
 // TwdmChannelTuningPerformanceMonitoringHistoryDataPart1ClassID is the 16-bit ID for the OMCI
 // Managed entity TWDM channel tuning performance monitoring history data part 1
-const TwdmChannelTuningPerformanceMonitoringHistoryDataPart1ClassID ClassID = ClassID(449)
+const TwdmChannelTuningPerformanceMonitoringHistoryDataPart1ClassID = ClassID(449) // 0x01c1
 
 var twdmchanneltuningperformancemonitoringhistorydatapart1BME *ManagedEntityDefinition
 
-// TwdmChannelTuningPerformanceMonitoringHistoryDataPart1 (class ID #449)
+// TwdmChannelTuningPerformanceMonitoringHistoryDataPart1 (Class ID: #449 / 0x01c1)
 //	This ME collects certain tuning-control-related PM data associated with the slot/circuit pack,
 //	hosting one or more ANI-G MEs, for a specific TWDM channel. Instances of this ME are created and
 //	deleted by the OLT.
@@ -48,27 +48,24 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the TWDM channel ME. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the TWDM channel ME. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 and 2 MEs
 //			that contains PM threshold values. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Tuning Control Requests For Rx Only Or Rx And Tx
-//			Tuning control requests for Rx only or Rx and Tx: The counter of received Tuning_Control PLOAM
-//			messages with Request operation code that contain tuning instructions either for receiver only
-//			or for both receiver and transmitter. (R) (mandatory) (4-byte)
+//			The counter of received Tuning_Control PLOAM messages with Request operation code that contain
+//			tuning instructions either for receiver only or for both receiver and transmitter. (R)
+//			(mandatory) (4-byte)
 //
 //		Tuning Control Requests For Tx Only
-//			Tuning control requests for Tx only: The counter of received Tuning_Control PLOAM messages with
-//			Request operation code that contain tuning instructions for transmitter only. (R) (mandatory)
-//			(4-byte)
+//			The counter of received Tuning_Control PLOAM messages with Request operation code that contain
+//			tuning instructions for transmitter only. (R) (mandatory) (4-byte)
 //
 //		Tuning Control Requests Rejected_Int_Sfc
 //			Tuning control requests rejected/INT_SFC: The counter of transmitted Tuning_Response PLOAM
@@ -86,24 +83,20 @@
 //			wavelength channel inconsistency. (R) (mandatory) (4-byte)
 //
 //		Tuning Control Requests Fulfilled With Onu Reacquired At Target Channel
-//			Tuning control requests fulfilled with ONU reacquired at target channel: The counter of
-//			controlled tuning attempts for which an upstream tuning confirmation has been obtained in the
-//			target channel. (R) (mandatory) (4-byte)
+//			The counter of controlled tuning attempts for which an upstream tuning confirmation has been
+//			obtained in the target channel. (R) (mandatory) (4-byte)
 //
 //		Tuning Control Requests Failed Due To Target Ds Wavelength Channel Not Found
-//			Tuning control requests failed due to target DS wavelength channel not found: The counter of
-//			controlled tuning attempts that failed due to timer TO4 expiration in the DS Tuning state (O8)
-//			in the target channel. (R) (mandatory) (4-byte)
+//			The counter of controlled tuning attempts that failed due to timer TO4 expiration in the DS
+//			Tuning state (O8) in the target channel. (R) (mandatory) (4-byte)
 //
 //		Tuning Control Requests Failed Due To No Feedback In Target Ds Wavelength Channel
-//			Tuning control requests failed due to no feedback in target DS wavelength channel: The counter
-//			of controlled tuning attempts that failed due to timer TO5 expiration in the US Tuning state
-//			(O9) in the target channel. (R) (mandatory) (4-byte)
+//			The counter of controlled tuning attempts that failed due to timer TO5 expiration in the US
+//			Tuning state (O9) in the target channel. (R) (mandatory) (4-byte)
 //
 //		Tuning Control Requests Resolved With Onu Reacquired At Discretionary Channel
-//			Tuning control requests resolved with ONU reacquired at discretionary channel: The counter of
-//			controlled tuning attempts for which an upstream tuning confirmation has been obtained in the
-//			discretionary channel. (R) (mandatory) (4-byte)
+//			The counter of controlled tuning attempts for which an upstream tuning confirmation has been
+//			obtained in the discretionary channel. (R) (mandatory) (4-byte)
 //
 //		Tuning Control Requests Rollback_Com_Ds
 //			Tuning control requests Rollback/COM_DS: The counter of controlled tuning attempts that failed
@@ -123,9 +116,8 @@
 //			(mandatory) (4-byte)
 //
 //		Tuning Control Requests Failed With Onu Reactivation
-//			Tuning control requests failed with ONU reactivation: The counter of controlled tuning attempts
-//			that failed on any reason, with expiration of timers TO4 or TO5 causing the ONU transition into
-//			state O1. (R) (mandatory) (4-byte)
+//			The counter of controlled tuning attempts that failed on any reason, with expiration of timers
+//			TO4 or TO5 causing the ONU transition into state O1. (R) (mandatory) (4-byte)
 //
 type TwdmChannelTuningPerformanceMonitoringHistoryDataPart1 struct {
 	ManagedEntityDefinition
diff --git a/generated/twdmchanneltuningperformancemonitoringhistorydatapart2.go b/generated/twdmchanneltuningperformancemonitoringhistorydatapart2.go
index 9e7d0e3..6dd4ca6 100644
--- a/generated/twdmchanneltuningperformancemonitoringhistorydatapart2.go
+++ b/generated/twdmchanneltuningperformancemonitoringhistorydatapart2.go
@@ -27,11 +27,11 @@
 
 // TwdmChannelTuningPerformanceMonitoringHistoryDataPart2ClassID is the 16-bit ID for the OMCI
 // Managed entity TWDM channel tuning performance monitoring history data part 2
-const TwdmChannelTuningPerformanceMonitoringHistoryDataPart2ClassID ClassID = ClassID(450)
+const TwdmChannelTuningPerformanceMonitoringHistoryDataPart2ClassID = ClassID(450) // 0x01c2
 
 var twdmchanneltuningperformancemonitoringhistorydatapart2BME *ManagedEntityDefinition
 
-// TwdmChannelTuningPerformanceMonitoringHistoryDataPart2 (class ID #450)
+// TwdmChannelTuningPerformanceMonitoringHistoryDataPart2 (Class ID: #450 / 0x01c2)
 //	This ME collects additional tuning-control-related PM data associated with the slot/circuit
 //	pack, hosting one or more ANI-G MEs, for a specific TWDM channel. Instances of this ME are
 //	created and deleted by the OLT.
@@ -47,13 +47,11 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the TWDM channel ME. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the TWDM channel ME. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 and 2 MEs
@@ -137,8 +135,8 @@
 			Create,
 			Delete,
 			Get,
-			GetCurrentData,
 			Set,
+			GetCurrentData,
 		),
 		AllowedAttributeMask: 0xfffe,
 		AttributeDefinitions: AttributeDefinitionMap{
diff --git a/generated/twdmchanneltuningperformancemonitoringhistorydatapart3.go b/generated/twdmchanneltuningperformancemonitoringhistorydatapart3.go
index ce12a7b..284f476 100644
--- a/generated/twdmchanneltuningperformancemonitoringhistorydatapart3.go
+++ b/generated/twdmchanneltuningperformancemonitoringhistorydatapart3.go
@@ -27,11 +27,11 @@
 
 // TwdmChannelTuningPerformanceMonitoringHistoryDataPart3ClassID is the 16-bit ID for the OMCI
 // Managed entity TWDM channel tuning performance monitoring history data part 3
-const TwdmChannelTuningPerformanceMonitoringHistoryDataPart3ClassID ClassID = ClassID(451)
+const TwdmChannelTuningPerformanceMonitoringHistoryDataPart3ClassID = ClassID(451) // 0x01c3
 
 var twdmchanneltuningperformancemonitoringhistorydatapart3BME *ManagedEntityDefinition
 
-// TwdmChannelTuningPerformanceMonitoringHistoryDataPart3 (class ID #451)
+// TwdmChannelTuningPerformanceMonitoringHistoryDataPart3 (Class ID: #451 / 0x01c3)
 //	This ME collects remaining tuning-control-related PM data associated with the slot/circuit pack,
 //	hosting one or more ANI-G MEs, for a specific TWDM channel. Instances of this ME are created and
 //	deleted by the OLT.
@@ -47,13 +47,11 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the TWDM channel ME. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the TWDM channel ME. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 and 2 MEs
@@ -113,8 +111,8 @@
 			Create,
 			Delete,
 			Get,
-			GetCurrentData,
 			Set,
+			GetCurrentData,
 		),
 		AllowedAttributeMask: 0xffc0,
 		AttributeDefinitions: AttributeDefinitionMap{
diff --git a/generated/twdmchannelxgemperformancemonitoringhistorydata.go b/generated/twdmchannelxgemperformancemonitoringhistorydata.go
index d7ee1e1..5b2311a 100644
--- a/generated/twdmchannelxgemperformancemonitoringhistorydata.go
+++ b/generated/twdmchannelxgemperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // TwdmChannelXgemPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity TWDM channel XGEM performance monitoring history data
-const TwdmChannelXgemPerformanceMonitoringHistoryDataClassID ClassID = ClassID(445)
+const TwdmChannelXgemPerformanceMonitoringHistoryDataClassID = ClassID(445) // 0x01bd
 
 var twdmchannelxgemperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// TwdmChannelXgemPerformanceMonitoringHistoryData (class ID #445)
+// TwdmChannelXgemPerformanceMonitoringHistoryData (Class ID: #445 / 0x01bd)
 //	This ME collects certain XGEM-related PM data associated with the slot/circuit pack, hosting one
 //	or more ANI-G MEs, for a specific TWDM channel. Instances of this ME are created and deleted by
 //	the OLT.
@@ -43,44 +43,38 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the TWDM channel ME. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the TWDM channel ME. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 64 Bit Id
 //			Threshold data 64-bit ID: This attribute points to an instance of the threshold data 64-bit ME
 //			that contains PM threshold values. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Total Transmitted Xgem Frames
-//			Total transmitted XGEM frames: The counter aggregated across all XGEM ports of the given ONU.
-//			(R) (mandatory) (8-byte)
+//			The counter aggregated across all XGEM ports of the given ONU. (R) (mandatory) (8-byte)
 //
 //		Transmitted Xgem Frames With Lf Bit Not Set
-//			Transmitted XGEM frames with LF bit not set: The counter aggregated across all XGEM ports of the
-//			given ONU identifies the number of fragmentation operations. (R) (mandatory) (8-byte)
+//			The counter aggregated across all XGEM ports of the given ONU identifies the number of
+//			fragmentation operations. (R) (mandatory) (8-byte)
 //
 //		Total Received Xgem Frames
-//			Total received XGEM frames: The counter aggregated across all XGEM ports of the given ONU. (R)
-//			(mandatory) (8-byte)
+//			The counter aggregated across all XGEM ports of the given ONU. (R) (mandatory) (8-byte)
 //
 //		Received Xgem Frames With Xgem Header Hec Errors
-//			Received XGEM frames with XGEM header HEC errors: The counter aggregated across all XGEM ports
-//			of the given ONU identifies the number of loss XGEM frame delineation events. (R) (mandatory)
-//			(8-byte)
+//			The counter aggregated across all XGEM ports of the given ONU identifies the number of loss XGEM
+//			frame delineation events. (R) (mandatory) (8-byte)
 //
 //		Fs Words Lost To Xgem Header Hec Errors
-//			FS words lost to XGEM header HEC errors: The counter of the FS frame words lost due to XGEM
-//			frame header errors that cause loss of XGEM frame delineation. (R) (mandatory) (8-byte)
+//			The counter of the FS frame words lost due to XGEM frame header errors that cause loss of XGEM
+//			frame delineation. (R) (mandatory) (8-byte)
 //
 //		Xgem Encryption Key Errors
-//			XGEM encryption key errors: The counter aggregated across all XGEM ports of the given ONU
-//			identifies the number of received XGEM frames that have to be discarded because of unknown or
-//			invalid encryption key. The number is included into the Total received XGEM frame count above.
-//			(R) (mandatory) (8-byte)
+//			The counter aggregated across all XGEM ports of the given ONU identifies the number of received
+//			XGEM frames that have to be discarded because of unknown or invalid encryption key. The number
+//			is included into the Total received XGEM frame count above. (R) (mandatory) (8-byte)
 //
 //		Total Transmitted Bytes In Non_Idle Xgem Frames
 //			Total transmitted bytes in non-idle XGEM frames: The counter aggregated across all XGEM ports of
@@ -103,8 +97,8 @@
 			Create,
 			Delete,
 			Get,
-			GetCurrentData,
 			Set,
+			GetCurrentData,
 		),
 		AllowedAttributeMask: 0xffc0,
 		AttributeDefinitions: AttributeDefinitionMap{
diff --git a/generated/uni-g.go b/generated/uni-g.go
index 58d8f6a..e7485fe 100644
--- a/generated/uni-g.go
+++ b/generated/uni-g.go
@@ -27,11 +27,11 @@
 
 // UniGClassID is the 16-bit ID for the OMCI
 // Managed entity UNI-G
-const UniGClassID ClassID = ClassID(264)
+const UniGClassID = ClassID(264) // 0x0108
 
 var unigBME *ManagedEntityDefinition
 
-// UniG (class ID #264)
+// UniG (Class ID: #264 / 0x0108)
 //	This ME organizes data associated with UNIs supported by GEM. One instance of the UNI-G ME
 //	exists for each UNI supported by the ONU.
 //
@@ -43,19 +43,35 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of a PPTP. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of a PPTP. (R) (mandatory) (2-bytes)
 //
 //		Deprecated
-//			Deprecated:	This attribute is not used. It should be set to 0 by the OLT and ignored by the ONU.
-//			(R,-W) (mandatory) (2-bytes)
+//			This attribute is not used. It should be set to 0 by the OLT and ignored by the ONU. (R,-W)
+//			(mandatory) (2-bytes)
 //
 //		Administrative State
+//			This attribute locks (1) and unlocks (0) the functions performed by this ME. Administrative
+//			state is further described in clause A.1.6. (R,-W) (mandatory) (1-byte)
+//
 //			NOTE - PPTP MEs also have an administrative state attribute. The user port is unlocked only if
 //			both administrative state attributes are set to unlocked. It is recommended that this attribute
 //			not be used: that the OLT set it to 0 and that the ONU ignore it.
 //
 //		Management Capability
+//			An ONU may support the ability for some or all of its PPTPs to be managed either directly by the
+//			OMCI or from a non-OMCI management environment such as [BBF TR-069]. This attribute advertises
+//			the ONU's capabilities for each PPTP.
+//
+//			This attribute is an enumeration with the following code points:
+//
+//			0	OMCI only
+//
+//			1	Non-OMCI only. In this case, the PPTP may be visible to the OMCI, but only in a read-only
+//			sense, e.g., for PM collection.
+//
+//			2	Both OMCI and non-OMCI
+//
 //			(R) (optional) (1-byte)
 //
 //		Non_Omci Management Identifier
@@ -65,8 +81,68 @@
 //			links to a non-OMCI management environment. (R,-W) (optional) (2-bytes)
 //
 //		Relay Agent Options
+//			%SL	In TR-101, this is called a slot. In an ONU, this variable refers to a shelf. It is
+//			meaningful if the ONU has multiple shelves internally or is daisy-chained to multiple equipment
+//			modules. The range of this variable is "0".. "99"
+//
+//			%SU	In TR-101, this is called a sub-slot. In fact, it represents a cardholder. The range of this
+//			variable is "0".. "99"
+//
+//			%PO	UNI port number. The range of this variable is "0".. "999"
+//
+//			%AE	ATM or Ethernet. This variable can take on the values "atm" or "eth".
+//
+//			%SV	S-VID for Ethernet UNI, or ATM VPI for ATM UNI, as it exists on the DHCP request received
+//			upstream across the UNI. Range "0".. "4096" for S-VID; range "0".. "255" for VPI. The value
+//			"4096" indicates no S-VID tag.
+//
+//			%CV	C-VID (Q-VID) for Ethernet UNI or ATM VCI for ATM UNI, as it exists on the DHCP request
+//			received upstream across the UNI. Range "0".. "4096" for C-VID; range "0".."65535" for VCI. The
+//			value "4096" indicates no C-VID tag.
+//
+//			Spaces in the provisioned string are significant.
+//
+//			Example: if the large string were provisioned with the value
+//
+//			%01%SL/%SU/%PO:%AE/%SV.%CV<null>,
+//
+//			then the ONU would generate the following DHCP option 82 agent circuitID string for an Ethernet
+//			UNI that sent a DHCP request with no S tag and C tag = 3210 on shelf 2, slot 3, port 4.
+//
+//			2/3/4:eth/4096.3210
+//
+//			With the same provisioning, the ONU would generate the following DHCP option 82 agent circuit-ID
+//			string for an ATM UNI that sent a DHCP request on VPI = 123 and VCI = 4567 on shelf 2, slot 3,
+//			port 4.
+//
 //			2/3/4:atm/123.4567
 //
+//			This attribute is a pointer to a large string ME whose content specifies one or more DHCP relay
+//			agent options. (R, W) (optional) (2-bytes)
+//
+//			The contents of the large string are parsed by the ONU and converted into text strings. Variable
+//			substitution is based on defined three-character groups, each of which begins with the '%'
+//			character. The string '%%' is an escape mechanism whose output is a single '%' character. When
+//			the ONU cannot perform variable substitution on a substring of the large string, it generates
+//			the specified option as an exact quotation of the provisioned substring value.
+//
+//			Provisioning of the large string is separate from the operation of setting the pointer in this
+//			attribute. It is the responsibility of the OLT to ensure that the large string contents are
+//			correct and meaningful.
+//
+//			Three-character variable definitions are as follows. The first variable in the large string must
+//			specify one of the option types. Both options for a given IP version may be present if desired,
+//			each introduced by its option identifier. Terminology is taken from clause 3.9.3 of [b-BBF
+//			TR-101].
+//
+//			%01, %18 Specifies that the following string is for option 82 sub-option 1, agent circuit-ID
+//			(IPv4) or option 18, interface-ID (IPv6). The equivalence permits the same large string to be
+//			used in both IP environments.
+//
+//			%02, %37 Specifies that the following string is for option 82 sub-option 2, relay agent remote-
+//			ID (IPv4) or option 37, relay agent remoteID (IPv6). The equivalence permits the same large
+//			string to be used in both IP environments.
+//
 type UniG struct {
 	ManagedEntityDefinition
 	Attributes AttributeValueMap
diff --git a/generated/vdsl2lineconfigurationextensions.go b/generated/vdsl2lineconfigurationextensions.go
new file mode 100644
index 0000000..ebac5a1
--- /dev/null
+++ b/generated/vdsl2lineconfigurationextensions.go
@@ -0,0 +1,375 @@
+/*
+ * 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.
+ */
+/*
+ * NOTE: This file was generated, manual edits will be overwritten!
+ *
+ * Generated by 'goCodeGenerator.py':
+ *              https://github.com/cboling/OMCI-parser/README.md
+ */
+
+package generated
+
+import "github.com/deckarep/golang-set"
+
+// Vdsl2LineConfigurationExtensionsClassID is the 16-bit ID for the OMCI
+// Managed entity VDSL2 line configuration extensions
+const Vdsl2LineConfigurationExtensionsClassID = ClassID(165) // 0x00a5
+
+var vdsl2lineconfigurationextensionsBME *ManagedEntityDefinition
+
+// Vdsl2LineConfigurationExtensions (Class ID: #165 / 0x00a5)
+//	This ME extends the xDSL line configuration MEs with attributes that were originally unique to
+//	ITU-T G.993.2 VDSL2. Due to continuing standards development, some attributes - and therefore
+//	this ME - have also become applicable to other Recommendations, specifically [ITU-T G.992.3] and
+//	[ITU-T G.992.5]. The attributes of this ME are further defined in [ITUT G.997.1]. An instance of
+//	this ME is created and deleted by the OLT.
+//
+//	Relationships
+//		An instance of this ME may be associated with zero or more instances of an xDSL UNI.////		The overall xDSL line configuration profile is modelled in several parts, all of which are
+//		associated together through a common ME ID (the client PPTP xDSL UNI part 1 has a single
+//		pointer, which refers to the entire set of line configuration parts).
+//
+//	Attributes
+//		Managed Entity Id
+//			This attribute uniquely identifies each instance of this ME. All xDSL and VDSL2 line
+//			configuration profiles and extensions that pertain to a given PPTP xDSL UNI must share a common
+//			ME ID. (R, setbycreate) (mandatory) (2-bytes)
+//
+//		Vdsl2 Profiles Enabling
+//			The PROFILES attribute contains the ITU-T G.993.2 profiles to be allowed by the xTU-C. It is
+//			coded in a bit map representation (0 if not allowed, 1 if allowed) with the following
+//			definition.
+//
+//			Bit	Meaning
+//
+//			1 (LSB)	ITU-T G.993.2 profile 8a
+//
+//			2	ITU-T G.993.2 profile 8b
+//
+//			3	ITU-T G.993.2 profile 8c
+//
+//			4	ITU-T G.993.2 profile 8d
+//
+//			5	ITU-T G.993.2 profile 12a
+//
+//			6	ITU-T G.993.2 profile 12b
+//
+//			7	ITU-T G.993.2 profile 17a
+//
+//			8	ITU-T G.993.2 profile 30a
+//
+//			(R,-W, setbycreate) (mandatory for ITU-T G.993.2) (1-byte)
+//
+//		Vdsl2 Psd Mask Class Selection Classmask
+//			NOTE 1 - A single PSD mask class may be selected per annex of [ITU-T G.993.2].
+//
+//			NOTE 2 - It is expected that only a single annex will be enabled at any given time, such that
+//			the CLASSMASK attribute, as well as the LIMITMASK and US0DISABLE attributes below, need not be
+//			vectors of values.
+//
+//			NOTE 3 - Attribute value 4 was formerly defined in [ITU-T G.997.1], and is no longer used.
+//
+//			(R,-W, setbycreate) (mandatory) (1-byte)
+//
+//			VDSL2 PSD mask class selection (CLASSMASK): To reduce the number of configuration possibilities,
+//			the limit PSD masks are grouped in the following PSD mask classes.
+//
+//			-	Class 998 Annex A of [ITU-T G.993.2]: D-32, D-48, D-64, D-128
+//
+//			-	Class 997-M1c Annex B of [ITU-T G.993.2]: 997M1c-A-7
+//
+//			-	Class 997-M1x Annex B of [ITU-T G.993.2]: 997M1x-M
+//
+//			-	Class 997-M2x Annex B of [ITU-T G.993.2]: 997E17-M2x-NUS0, 997E30M2xNUS0
+//
+//			-	Class 998-M2x Annex B of [ITU-T G.993.2]: 998M2x-A, 998M2xM, 998M2x-B, 998-M2x-NUS0,
+//			998E17-M2xNUS0, 998E17M2xNUS0-M, 998E30M2xNUS0, 998E30M2xNUS0M, 998E17-M2x-A
+//
+//			-	Class 998ADE-M2x Annex B of [ITU-T G.993.2]: 998-M2x-A, 998M2x-M, 998-M2x-B, 998-M2x-NUS0,
+//			998ADE17-M2x-A, 998ADE17M2xB, 998ADE17-M2x-M, 998ADE17M2xNUS0-M, 998ADE30M2xNUS0-A,
+//			998ADE30M2x-NUS0-M, HPEADE1230, HPEADE1730
+//
+//			-	Class 998-B Annex C: POTS-138b, POTS-276b (clause C.2.1.1 of [ITUT-G.993.2]), TCMISDN (clause
+//			C.2.1.2 of [ITU-T G.993.2])
+//
+//			-	Class 998-CO Annex C of [ITU-T G.993.2]: POTS138co, POTS276co (clause C.2.1.1 of [ITU-T
+//			G.993.2])
+//
+//			-	Class HPE-M1 Annex B of [ITU-T G.993.2]: HPE17M1-NUS0, HPE30M1NUS0, HPE1230-M1-NUS0,
+//			HPE1730-M1-NUS0
+//
+//			Each class is designed such that the PSD levels of each limit PSD mask of a specific class are
+//			equal in their respective passbands above 552 kHz.
+//
+//			The CLASSMASK attribute is defined per annex of [ITU-T G.993.2] enabled in the xTSE table (see
+//			Table 9.7.12-1). It selects a single PSD mask class per annex of [ITU-T G.993.2] to be activated
+//			at the very high-speed digital subscriber line transceiver unit, operator end (VTU-O). The
+//			coding is as follows:
+//
+//		Vdsl2 Limit Psd Masks
+//			The LIMITMASK attribute contains the ITU-T G.993.2 limit PSD masks of the selected PSD mask
+//			class, enabled by the near-end xTU for each class of profiles. One LIMITMASK parameter is
+//			defined per annex enabled in the xTSE (see Table 9.7.12-1).
+//
+//			The profiles are grouped in the following profile classes:
+//
+//			-	Class 8: Profiles 8a, 8b, 8c, 8d
+//
+//			-	Class 12: Profiles 12a, 12b
+//
+//			-	Class 17: Profile 17a
+//
+//			-	Class 30: Profile 30a
+//
+//			For each profile class, several limit PSD masks of the selected PSD mask class (CLASSMASK) may
+//			be enabled. The enabling attribute is coded in a bit map representation (0 if the associated
+//			mask is not allowed, 1 if it is allowed). The bit mask is defined in Table 9.7.6-1. (R,-W,
+//			setbycreate) (mandatory) (8-bytes)
+//
+//		Vdsl2 Us0 Disabling
+//			The US0DISABLE attribute specifies whether channel US0 is disabled for each limit PSD mask
+//			enabled in the LIMITMASK attribute.
+//
+//			For each limit PSD mask enabled in the LIMITMASK attribute, one bit indicates if US0 is
+//			disabled. The disabling attribute is a bit map where the value 1 specifies that US0 is disabled
+//			for the associated limit mask. The bit map has the same structure as the LIMITMASK attribute.
+//			(R,-W, setbycreate) (mandatory) (8-bytes)
+//
+//		Vdsl2 Us0 Psd Masks
+//			The US0MASK attribute contains the US0 PSD masks to be allowed by the xTU-C. This attribute is
+//			only defined for Annex-A of [ITUT-G.993.2]. It is represented as a bit map (0 if not allowed, 1
+//			if allowed) with the definitions of Table-9.7.6-2. (R, W, setbycreate) (mandatory) (4-bytes)
+//
+//		Vdsl2_Carmask Table
+//			VDSL2-CARMASK table: This attribute specifies restrictions, additional to the band plan, that
+//			determine the set of subcarriers allowed for transmission in both upstream and downstream
+//			directions.
+//
+//			The VDSL2-CARMASK attribute describes the not-masked subcarriers in terms of one or more
+//			frequency bands. Each band is represented by start and stop subcarrier indices with a subcarrier
+//			spacing of 4.3125-kHz. The valid range of subcarrier indices is from 0 to at least the index of
+//			the highest allowed subcarrier in both transmission directions among all profiles enabled by the
+//			VDSL2 profiles enabling (PROFILES) attribute. Up to 32 bands may be specified. Other subcarriers
+//			are masked.
+//
+//			For profiles using 8.625 kHz tone spacing, the odd subcarrier indices i4.3125 in VDSL2-CARMASK
+//			can be transformed into actual subcarrier indices i8.625 using the following rule:
+//
+//			- for the start frequency of each band: i8.625-=-(i4.3125 + 1)/2
+//
+//			- for the stop frequency of each band: i8.625-=-(i4.3125 - 1)/2.
+//
+//			The VDSL2-CARMASK attribute is a table where each entry comprises:
+//
+//			- an entry number field (1-byte, first entry numbered 1);
+//
+//			- band start subcarrier index (2-bytes);
+//
+//			- band stop subcarrier index (2-bytes).
+//
+//			By default, the table is empty. Entries are added or modified using the set action. Setting a
+//			table entry with non-zero subcarrier references implies insertion into the table. Setting an
+//			entry's subcarrier references to zero implies deletion from the table, if present.
+//
+//			The maximum number of bands is 32, so the maximum size of the table is 160-bytes. (R,-W)
+//			(mandatory) (5 * N bytes, where N is the number of bands)
+//
+//		Carmask Valid
+//			This attribute controls and reports the status of the VDSL2-CARMASK table. If CARMASK valid-= 1,
+//			then the VDSL2-CARMASK has been effectuated on the xDSL equipment. If CARMASK valid-= 0
+//			(default), then the VDSL2-CARMASK table is under construction and has not been effectuated on
+//			the xDSL equipment.
+//
+//			This attribute behaves as follows.
+//
+//			If the OLT changes any of the VDSL2-CARMASK table entries or sets CARMASK valid-= 0, then
+//			CARMASK valid-= 0.
+//
+//			If CARMASK valid-= 0 and the OLT sets CARMASK valid-= 1, then the ONU updates the xDSL equipment
+//			with the contents of the table.
+//
+//			(R,-W) (mandatory) (1-byte)
+//
+//		Upboshaped
+//			This attribute includes two parameters for each band. The parameters are a and b, in that order.
+//			Parameter a lies in the range 4000 (40.00-dBm/Hz) to 8095 (80.95-dBm/Hz). Parameter b lies in
+//			the range 0 (0.00-dBm/Hz) to 4095 (40.95-dBm/Hz). The special values a-= b-= 0 disable UPBO in
+//			the respective upstream band.
+//
+//			The upstream electrical length parameter UPBOKL defines the electrical length expressed in
+//			decibels at 1-MHz, kl0, which may also be configured by the OLT. Its value ranges from 0
+//			(0.0-dB) to 1280 (128.0-dB).
+//
+//			If the force electrical length parameter UPBOKLF is 1, the very high-speed digital subscriber
+//			line transceiver unit, remote end (VTU-R) is forced to use the electrical length from this
+//			attribute (UPBOKL) to compute UPBO. Otherwise, the VDSL2 transceiver units (VTUs) determine the
+//			electrical length themselves.
+//
+//			(R,-W) (mandatory) (23-bytes)
+//
+//			Upstream power back-off (UPBO) is specified in [ITUT G.993.2] to provide spectral compatibility
+//			between loops of different lengths deployed in the same cable binder. The upstream transmit PSD
+//			mask, UPBOMASKus is defined in clause 7.2.1.3.2 of [ITUT G.993.2].
+//
+//			The ITU-T G.993.2 UPBO configuration attributes a and b are set by the OLT via this attribute.
+//			The reference length kl0_REF is set by the companion attribute UPBO klREF-pb, defined in the
+//			following. Further details appear in [ITUT-G.997.1].
+//
+//		Cyclic Extension
+//			The CEFLAG attribute enables (1) the optional cyclic extension values. If set to 0, the cyclic
+//			extension is forced to the mandatory length 5N/32. (R,-W) (mandatory) (1-byte)
+//
+//		Downstream Signal_To_Noise Ratio Snr Mode
+//			Downstream signal-to-noise ratio (SNR) mode: The SNRMODEds attribute controls transmitter
+//			referred virtual noise in the downstream direction. If set to 1, virtual noise is disabled. If
+//			set to 2, virtual noise is enabled. (R,-W) (mandatory) (1-byte)
+//
+//		Upstream Snr Mode
+//			The SNRMODEus attribute controls transmitter referred virtual noise in the upstream direction.
+//			If set to 1, virtual noise is disabled. If set to 2, virtual noise is enabled. (R,-W)
+//			(mandatory) (1-byte)
+//
+//		Transmitter Referred Virtual Noise Downstream Table
+//			Table entries for this attribute have the default value 254 for the noise PSD level. Entries are
+//			added or modified using the set action. Setting an entry to a noise PSD level less than or equal
+//			to 254 implies insertion into the table. Setting an entry's noise PSD level to 255 implies
+//			deletion from the table, if present.
+//
+//			(R,-W) (optional) (3N bytes, where N is the number of breakpoints)
+//
+//			The TXREFVNds table defines the downstream transmitter referred virtual noise. TXREFVNds is
+//			specified through a set of breakpoints. Each breakpoint comprises a subcarrier index t, with a
+//			subcarrier spacing of 4.3125-kHz, and a noise PSD level at that subcarrier. The set of
+//			breakpoints can then be represented as [(t1, PSD1), (t2, PSD2), ..., (tN, PSDN)]. The subcarrier
+//			index t is an unsigned 2 byte integer. The noise level is 1-byte whose value ranges from 0
+//			(-40-dBm/Hz) to 200 (-140-dBm/Hz), in steps of 0.5 dB. Values between 201 and 254 indicate a
+//			noise PSD level of 0 W/Hz. The maximum number of breakpoints is 32; no more than 15 breakpoints
+//			may be configured below the upper edge of the passband of every mode enabled for [ITU-T G.992.3]
+//			and [ITUT-G.992.5].
+//
+//		Transmitter Referred Virtual Noise Upstream Table
+//			The TXREFVNus attribute defines the upstream transmitter referred virtual noise. TXREFVNus is
+//			specified through a set of breakpoints. Each breakpoint comprises a subcarrier index t, with a
+//			subcarrier spacing of 4.3125-kHz, and a noise PSD level at that subcarrier. The set of
+//			breakpoints can then be represented as [(t1, PSD1), (t2, PSD2), ..., (tN, PSDN)]. The subcarrier
+//			index t is an unsigned 2-byte integer. The noise level is 1-byte whose value ranges from 0
+//			(-40-dBm/Hz) to 200 (-140-dBm/Hz), in steps of 0.5 dB. Values between 201 and 254 indicate a
+//			noise PSD level of 0-W/Hz. The maximum number of breakpoints is 16; no more than three
+//			breakpoints may be configured below the upper edge of the passband of every mode enabled for
+//			[ITU-T G.992.3] and [ITUT-G.992.5].
+//
+//			Table entries for this attribute have the default value 254 for the noise PSD level. Entries are
+//			added or modified using the set action. Setting an entry to a noise PSD level less than or equal
+//			to 254 implies insertion into the table. Setting an entry's noise PSD level to 255 implies
+//			deletion from the table, if present.
+//
+//			(R,-W) (optional) (3N bytes, where N is the number of breakpoints)
+//
+//		Dpboshaped
+//			Downstream power back-off - shaped is described in [ITUT G.997.1] as a vector of parameters that
+//			modifies the downstream PSD mask.
+//
+//			DPBOEPSD - Assumed exchange PSD mask. This component points to a downstream xDSL PSD mask
+//			profile ME. The PSD mask profile should contain no more than 16 break points. (2-bytes)
+//
+//			DPBOESEL - E-side electrical length. This component is the assumed loss at some reference
+//			frequency of the electrical cable from the xDSL equipment to a possible flexibility point. It
+//			ranges from 0 (0.0-dB) to 511 (255.5-dB) in steps of 0.5-dB. The value 0 has the special meaning
+//			that it disables the DPBOSHAPED feature. (2-bytes)
+//
+//			The following three parameters describe the cable model. Further details appear in [ITUT
+//			G.997.1]. Each is a scalar that represents the range -1 (coded as 0) to +1.5 (coded as 640) in
+//			steps of 1/256.
+//
+//			DPBOESCMA - (2-bytes)
+//
+//			DPBOESCMB - (2-bytes)
+//
+//			DPBOESCMC - (2-bytes)
+//
+//			DPBOMUS - Assumed minimum usable receive PSD mask. This component ranges from 0 (0.0-dBm/Hz) to
+//			255 (-127.5-dBm/Hz) in steps of 0.5 dB. (1-byte)
+//
+//			DPBOFMIN - The lower frequency bound above which DPBO is applied. This component ranges from 0
+//			(0.00 kHz) to 2048 (8832.00 kHz) in steps of 4.3125 kHz. (2-bytes)
+//
+//			DPBOFMAX - The upper frequency bound below which DPBO is applied. This component ranges from 32
+//			(138.00-kHz) to 6956 (29997.75-kHz) in steps of 4.3125-kHz. (2-bytes)
+//
+//			(R,-W) (optional) (15-bytes)
+//
+//		Upboklref_Pb
+//			UPBOKLREF-pb: This attribute represents the reference loop length, the electrical length used to
+//			compute upstream power back-off (UPBO) for each upstream band except US0, for the optional
+//			equalized FEXT UPBO method. The value for each upstream band ranges from 1.8 to 63.5 dB in steps
+//			of 0.1 dB, i.e., with values 18..635. The special value 0 is also allowed, with semantics as
+//			defined in clause 7.2.1.3.2 of [ITUT G.993.2]. (R,-W) (optional) (2-bytes * 5 upstream bands)
+//
+//		Upboshaped Aele_Mode, Upboelmt
+//			UPBOSHAPED (AELE-MODE, UPBOELMT): This attribute defines the UPBO electrical length estimation
+//			mode (AELE-MODE) and UPBO electrical length minimum threshold percentile (UPBOELMT) to be used
+//			in the alternative electrical length estimation method (ELE-M1). The format of this attribute is
+//			given in octet 1 of Table 12-27 of [ITU-T G.993.2]. (R,-W) (optional) (1-byte)
+//
+type Vdsl2LineConfigurationExtensions struct {
+	ManagedEntityDefinition
+	Attributes AttributeValueMap
+}
+
+func init() {
+	vdsl2lineconfigurationextensionsBME = &ManagedEntityDefinition{
+		Name:    "Vdsl2LineConfigurationExtensions",
+		ClassID: 165,
+		MessageTypes: mapset.NewSetWith(
+			Create,
+			Delete,
+			Get,
+			GetNext,
+			Set,
+			SetTable,
+		),
+		AllowedAttributeMask: 0xffff,
+		AttributeDefinitions: AttributeDefinitionMap{
+			0:  Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read, SetByCreate), false, false, false, 0),
+			1:  ByteField("Vdsl2ProfilesEnabling", UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 1),
+			2:  ByteField("Vdsl2PsdMaskClassSelectionClassmask", UnsignedIntegerAttributeType, 0x4000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 2),
+			3:  Uint64Field("Vdsl2LimitPsdMasks", UnsignedIntegerAttributeType, 0x2000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 3),
+			4:  Uint64Field("Vdsl2Us0Disabling", UnsignedIntegerAttributeType, 0x1000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 4),
+			5:  Uint32Field("Vdsl2Us0PsdMasks", UnsignedIntegerAttributeType, 0x0800, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 5),
+			6:  TableField("Vdsl2CarmaskTable", TableAttributeType, 0x0400, TableInfo{nil, 5}, mapset.NewSetWith(Read, Write), false, false, false, 6),
+			7:  ByteField("CarmaskValid", UnsignedIntegerAttributeType, 0x0200, 0, mapset.NewSetWith(Read, Write), false, false, false, 7),
+			8:  MultiByteField("Upboshaped", OctetsAttributeType, 0x0100, 23, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="), mapset.NewSetWith(Read, Write), false, false, false, 8),
+			9:  ByteField("CyclicExtension", UnsignedIntegerAttributeType, 0x0080, 0, mapset.NewSetWith(Read, Write), false, false, false, 9),
+			10: ByteField("DownstreamSignalToNoiseRatioSnrMode", UnsignedIntegerAttributeType, 0x0040, 0, mapset.NewSetWith(Read, Write), false, false, false, 10),
+			11: ByteField("UpstreamSnrMode", UnsignedIntegerAttributeType, 0x0020, 0, mapset.NewSetWith(Read, Write), false, false, false, 11),
+			12: TableField("TransmitterReferredVirtualNoiseDownstreamTable", TableAttributeType, 0x0010, TableInfo{nil, 3}, mapset.NewSetWith(Read, Write), false, true, false, 12),
+			13: TableField("TransmitterReferredVirtualNoiseUpstreamTable", TableAttributeType, 0x0008, TableInfo{nil, 3}, mapset.NewSetWith(Read, Write), false, true, false, 13),
+			14: MultiByteField("Dpboshaped", OctetsAttributeType, 0x0004, 15, toOctets("AAAAAAAAAAAAAAAAAAAA"), mapset.NewSetWith(Read, Write), false, true, false, 14),
+			15: Uint16Field("UpboklrefPb", UnsignedIntegerAttributeType, 0x0002, 0, mapset.NewSetWith(Read, Write), false, true, false, 15),
+			16: ByteField("UpboshapedAeleMode,Upboelmt", UnsignedIntegerAttributeType, 0x0001, 0, mapset.NewSetWith(Read, Write), false, true, false, 16),
+		},
+		Access:  CreatedByOlt,
+		Support: UnknownSupport,
+	}
+}
+
+// NewVdsl2LineConfigurationExtensions (class ID 165) creates the basic
+// Managed Entity definition that is used to validate an ME of this type that
+// is received from or transmitted to the OMCC.
+func NewVdsl2LineConfigurationExtensions(params ...ParamData) (*ManagedEntity, OmciErrors) {
+	return NewManagedEntity(*vdsl2lineconfigurationextensionsBME, params...)
+}
diff --git a/generated/vdsl2lineconfigurationextensions2.go b/generated/vdsl2lineconfigurationextensions2.go
index 844bb19..86f2383 100644
--- a/generated/vdsl2lineconfigurationextensions2.go
+++ b/generated/vdsl2lineconfigurationextensions2.go
@@ -27,11 +27,11 @@
 
 // Vdsl2LineConfigurationExtensions2ClassID is the 16-bit ID for the OMCI
 // Managed entity VDSL2 line configuration extensions 2
-const Vdsl2LineConfigurationExtensions2ClassID ClassID = ClassID(323)
+const Vdsl2LineConfigurationExtensions2ClassID = ClassID(323) // 0x0143
 
 var vdsl2lineconfigurationextensions2BME *ManagedEntityDefinition
 
-// Vdsl2LineConfigurationExtensions2 (class ID #323)
+// Vdsl2LineConfigurationExtensions2 (Class ID: #323 / 0x0143)
 //	This ME extends the xDSL line configuration MEs. The ME name was chosen because its attributes
 //	were initially unique to ITU-T G.993.2 VDSL2. Due to continuing standards development, two of
 //	the attributes (FEXT and NEXT TXREFVNds) are also used in [ITUT-G.992.3] and [ITUT-G.992.5].
@@ -49,113 +49,107 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. All xDSL and
-//			VDSL2 line configuration profiles and extensions that pertain to a given PPTP xDSL must share a
-//			common ME ID. (R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. All xDSL and VDSL2 line
+//			configuration profiles and extensions that pertain to a given PPTP xDSL must share a common ME
+//			ID. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Sos Time Downstream
-//			SOS time downstream: The SOS-TIME-ds attribute is used in the specification of receiver
-//			initiated SOS (see clause 13.4.3 of [ITUT G.993.2]). If the attribute value is not zero, the
-//			standard SOS triggering criteria are enabled, and the value specifies the duration of the window
-//			used in the standard SOS triggering criteria in the downstream direction. The special value zero
-//			indicates that the standard SOS triggering criteria are disabled, i.e., vendor-discretionary
-//			values may be used instead of the values configured in the MIB for the following parameters:
-//			SOS-NTONES-ds, SOS-CRC-ds, SOS-TIME-ds. The valid range of non-zero values is from 1..255,
-//			specifying 64-ms to 16320 ms in steps of 64-ms. (R,-W, setbycreate) (optional) (1-byte)
+//			The SOS-TIME-ds attribute is used in the specification of receiver initiated SOS (see clause
+//			13.4.3 of [ITUT G.993.2]). If the attribute value is not zero, the standard SOS triggering
+//			criteria are enabled, and the value specifies the duration of the window used in the standard
+//			SOS triggering criteria in the downstream direction. The special value zero indicates that the
+//			standard SOS triggering criteria are disabled, i.e., vendor-discretionary values may be used
+//			instead of the values configured in the MIB for the following parameters: SOS-NTONES-ds, SOS-
+//			CRC-ds, SOS-TIME-ds. The valid range of non-zero values is from 1..255, specifying 64-ms to
+//			16320 ms in steps of 64-ms. (R,-W, setbycreate) (optional) (1-byte)
 //
 //		Sos Time Upstream
-//			SOS time upstream: The SOS-TIME-us attribute is used in the specification of receiver initiated
-//			SOS (see clause 13.4.3 of [ITUT G.993.2]). If the attribute value is not zero, the standard SOS
-//			triggering criteria are enabled, and the value specifies the duration of the window used in the
-//			standard SOS triggering criteria in the upstream direction. The special value zero indicates
-//			that the standard SOS triggering criteria are disabled, i.e., vendor-discretionary values may be
-//			used instead of the values configured in the MIB for the following parameters: SOS-NTONES-us,
-//			SOS-CRC-us, SOS-TIME-us. The valid range of non-zero values is from 1..255, specifying 64-ms to
+//			The SOS-TIME-us attribute is used in the specification of receiver initiated SOS (see clause
+//			13.4.3 of [ITUT G.993.2]). If the attribute value is not zero, the standard SOS triggering
+//			criteria are enabled, and the value specifies the duration of the window used in the standard
+//			SOS triggering criteria in the upstream direction. The special value zero indicates that the
+//			standard SOS triggering criteria are disabled, i.e., vendor-discretionary values may be used
+//			instead of the values configured in the MIB for the following parameters: SOS-NTONES-us, SOS-
+//			CRC-us, SOS-TIME-us. The valid range of non-zero values is from 1..255, specifying 64-ms to
 //			16320-ms in steps of 64-ms. (R,-W, setbycreate) (optional) (1-byte)
 //
 //		Sos Degraded Tones Threshold Downstream
-//			SOS degraded tones threshold downstream: The SOS-NTONES-ds attribute is the minimum percentage
-//			of tones in the downstream medley set that must be degraded in order to arm the first
-//			subcondition of the standard SOS triggering criteria in the downstream direction. The valid
-//			range of values is from 1 to 100% in steps of 1. Use of the special value 0 is described in
-//			clause 13.4.3.2 of [ITUT G.993.2]. (R,-W, setbycreate) (optional) (1-byte)
+//			The SOS-NTONES-ds attribute is the minimum percentage of tones in the downstream medley set that
+//			must be degraded in order to arm the first subcondition of the standard SOS triggering criteria
+//			in the downstream direction. The valid range of values is from 1 to 100% in steps of 1. Use of
+//			the special value 0 is described in clause 13.4.3.2 of [ITUT G.993.2]. (R,-W, setbycreate)
+//			(optional) (1-byte)
 //
 //		Sos Degraded Tones Threshold Upstream
-//			SOS degraded tones threshold upstream: The SOS-NTONES-us attribute is the minimum percentage of
-//			tones in the upstream medley set that must be degraded in order to arm the first subcondition of
-//			the standard SOS triggering criteria in the upstream direction. The valid range of values is
-//			from 1 to 100% in steps of 1. Use of the special value 0 is described in clause 13.4.3.2 of
-//			[ITUT-G.993.2]. (R,-W, setbycreate) (optional) (1-byte)
+//			The SOS-NTONES-us attribute is the minimum percentage of tones in the upstream medley set that
+//			must be degraded in order to arm the first subcondition of the standard SOS triggering criteria
+//			in the upstream direction. The valid range of values is from 1 to 100% in steps of 1. Use of the
+//			special value 0 is described in clause 13.4.3.2 of [ITUT-G.993.2]. (R,-W, setbycreate)
+//			(optional) (1-byte)
 //
 //		Sos Crc Threshold Downstream
-//			SOS CRC threshold downstream: The SOS-CRC-ds attribute is the minimum number of normalized CRC
-//			anomalies received in SOS-TIME-ds seconds in order to arm the second sub-condition of the
-//			standard SOS triggering criteria (see clause 13.4.3.2 of [ITU T G.993.2]) in the downstream
-//			direction. The valid range of SOS-CRC values is 0.02 to (216-1)*0.02, in steps of 0.02. The
-//			value-0 specifies that the ONU uses its internal default. (R, W, set-by-create) (optional) (2
-//			bytes)
+//			The SOS-CRC-ds attribute is the minimum number of normalized CRC anomalies received in SOS-TIME-
+//			ds seconds in order to arm the second sub-condition of the standard SOS triggering criteria (see
+//			clause 13.4.3.2 of [ITU T G.993.2]) in the downstream direction. The valid range of SOS-CRC
+//			values is 0.02 to (216-1)*0.02, in steps of 0.02. The value-0 specifies that the ONU uses its
+//			internal default. (R, W, set-by-create) (optional) (2 bytes)
 //
 //		Sos Crc Threshold Upstream
-//			SOS CRC threshold upstream: The SOS-CRC-us attribute is the minimum number of normalized CRC
-//			anomalies received in SOS-TIME-us seconds in order to arm the second sub-condition of the
-//			standard SOS triggering criteria (see clause 13.4.3.2 of [ITU T G.993.2]) in the upstream
-//			direction. The valid range of SOS-CRC values is 0.02 to (216-1)*0.02, in steps of 0.02. The
-//			value-0 specifies that the ONU uses its internal default. (R, W, set-by-create) (optional) (2
-//			bytes)
+//			The SOS-CRC-us attribute is the minimum number of normalized CRC anomalies received in SOS-TIME-
+//			us seconds in order to arm the second sub-condition of the standard SOS triggering criteria (see
+//			clause 13.4.3.2 of [ITU T G.993.2]) in the upstream direction. The valid range of SOS-CRC values
+//			is 0.02 to (216-1)*0.02, in steps of 0.02. The value-0 specifies that the ONU uses its internal
+//			default. (R, W, set-by-create) (optional) (2 bytes)
 //
 //		Max Sos Downstream
-//			MAX SOS downstream: The MAX-SOS-ds attribute is used in deactivation. If the number of
-//			successful SOS procedures in the downstream direction performed within a 120-s interval exceeds
-//			MAX-SOS-ds, the modem goes to state L3. See clause 12.1.4 of [ITUT G.993.2] for details. The
-//			valid range of values is 1 to 15, with the special value 0 as described in clause 12.1 of [ITUT
-//			G.993.2]. (R,-W, setbycreate) (optional) (1-byte)
+//			The MAX-SOS-ds attribute is used in deactivation. If the number of successful SOS procedures in
+//			the downstream direction performed within a 120-s interval exceeds MAX-SOS-ds, the modem goes to
+//			state L3. See clause 12.1.4 of [ITUT G.993.2] for details. The valid range of values is 1 to 15,
+//			with the special value 0 as described in clause 12.1 of [ITUT G.993.2]. (R,-W, setbycreate)
+//			(optional) (1-byte)
 //
 //		Max Sos Upstream
-//			MAX SOS upstream: The MAX-SOS-us attribute is used in deactivation. If the number of successful
-//			SOS procedures in the upstream direction performed within a 120-s interval exceeds MAX-SOS-us,
-//			the modem goes to state L3. See clause 12.1.4 of [ITUT G.993.2] for details. The valid range of
-//			values is 1 to 15, with the special value 0 as described in clause 12.1 of [ITUT G.993.2].
-//			(R,-W, setbycreate) (optional) (1-byte)
+//			The MAX-SOS-us attribute is used in deactivation. If the number of successful SOS procedures in
+//			the upstream direction performed within a 120-s interval exceeds MAX-SOS-us, the modem goes to
+//			state L3. See clause 12.1.4 of [ITUT G.993.2] for details. The valid range of values is 1 to 15,
+//			with the special value 0 as described in clause 12.1 of [ITUT G.993.2]. (R,-W, setbycreate)
+//			(optional) (1-byte)
 //
 //		Snr Max Offset Downstream
-//			SNR max offset downstream: The SNRMOFFSET-ROC-ds attribute is the SNR margin offset for the ROC
-//			in the downstream direction. The attribute is used in the specification of the channel
-//			initialization policy (see clause 12.3.7.1 of [ITUT G.993.2]). The valid range of SNR margin
-//			offset values is from 0..31-dB in 0.1-dB steps. (R,-W, setbycreate) (optional) (2-bytes)
+//			The SNRMOFFSET-ROC-ds attribute is the SNR margin offset for the ROC in the downstream
+//			direction. The attribute is used in the specification of the channel initialization policy (see
+//			clause 12.3.7.1 of [ITUT G.993.2]). The valid range of SNR margin offset values is from 0..31-dB
+//			in 0.1-dB steps. (R,-W, setbycreate) (optional) (2-bytes)
 //
 //		Snr Max Offset Upstream
-//			SNR max offset upstream: The SNRMOFFSET-ROC-us attribute is the SNR margin offset for the ROC in
-//			the upstream direction. The attribute is used in the specification of the channel initialization
-//			policy (see clause-12.3.7.1 of [ITUT G.993.2]). The valid range of SNR margin offset values is
-//			from 0..31-dB in 0.1-dB steps. (R,-W, setbycreate) (optional) (2-bytes)
+//			The SNRMOFFSET-ROC-us attribute is the SNR margin offset for the ROC in the upstream direction.
+//			The attribute is used in the specification of the channel initialization policy (see
+//			clause-12.3.7.1 of [ITUT G.993.2]). The valid range of SNR margin offset values is from 0..31-dB
+//			in 0.1-dB steps. (R,-W, setbycreate) (optional) (2-bytes)
 //
 //		Roc Minimum Impulse Noise Protection Downstream
-//			ROC minimum impulse noise protection downstream: The INPMIN-ROC-ds attribute specifies the
-//			minimum INP to apply on the ROC in the downstream direction expressed in multiples of equivalent
-//			4k DMT, xDSL (DMT) symbol length. The minimum INP is an integer ranging from 0 to 8. (R,-W,
-//			setbycreate) (optional) (1-byte)
+//			The INPMIN-ROC-ds attribute specifies the minimum INP to apply on the ROC in the downstream
+//			direction expressed in multiples of equivalent 4k DMT, xDSL (DMT) symbol length. The minimum INP
+//			is an integer ranging from 0 to 8. (R,-W, setbycreate) (optional) (1-byte)
 //
 //		Roc Minimum Impulse Noise Protection Upstream
-//			ROC minimum impulse noise protection upstream: The INPMIN-ROC-us attribute specifies the minimum
-//			impulse noise protection to apply on the ROC in the upstream direction expressed in multiples of
-//			equivalent 4k DMT symbol length. The minimum INP is an integer ranging from 0 to 8. (R,-W,
-//			setbycreate) (optional) (1-byte)
+//			The INPMIN-ROC-us attribute specifies the minimum impulse noise protection to apply on the ROC
+//			in the upstream direction expressed in multiples of equivalent 4k DMT symbol length. The minimum
+//			INP is an integer ranging from 0 to 8. (R,-W, setbycreate) (optional) (1-byte)
 //
 //		Fext Downstream Transmitter Referred Virtual Noise Table
-//			FEXT downstream transmitter referred virtual noise table: The FEXT TXREFVNds attribute is the
-//			downstream transmitter referred virtual noise specified for FEXTR duration in Annex C of [ITUT
-//			G.992.3] (ADSL2) and Annex C of [ITUT G.992.5] (ADSL2plus). The syntax of this attribute is the
-//			same as that of the TXREFVNds table attribute of the VDSL2 line configuration extensions ME.
-//			(R,-W) (mandatory for Annex-C of [ITUT-G.992.3] and Annex-C of [ITUT-G.992.5]) (3-*-N bytes,
-//			where N is the number of breakpoints)
+//			The FEXT TXREFVNds attribute is the downstream transmitter referred virtual noise specified for
+//			FEXTR duration in Annex C of [ITUT G.992.3] (ADSL2) and Annex C of [ITUT G.992.5] (ADSL2plus).
+//			The syntax of this attribute is the same as that of the TXREFVNds table attribute of the VDSL2
+//			line configuration extensions ME. (R,-W) (mandatory for Annex-C of [ITUT-G.992.3] and Annex-C of
+//			[ITUT-G.992.5]) (3-*-N bytes, where N is the number of breakpoints)
 //
 //		Next Downstream Transmitter Referred Virtual Noise Table
-//			NEXT downstream transmitter referred virtual noise table: The NEXT TXREFVNds attribute is the
-//			downstream transmitter referred virtual noise specified for NEXTR duration in Annex C of [ITUT
-//			G.992.3] (ADSL2) and Annex C of [ITUT G.992.5] (ADSL2plus). The syntax of this attribute is the
-//			same as that of the TXREFVNds table attribute of the VDSL2 line configuration extensions ME.
-//			(R,-W) (mandatory for Annex-C of [ITUT-G.992.3] and Annex-C of [ITUT-G.992.5]) (3-*-N bytes,
-//			where N is the number of breakpoints)
+//			The NEXT TXREFVNds attribute is the downstream transmitter referred virtual noise specified for
+//			NEXTR duration in Annex C of [ITUT G.992.3] (ADSL2) and Annex C of [ITUT G.992.5] (ADSL2plus).
+//			The syntax of this attribute is the same as that of the TXREFVNds table attribute of the VDSL2
+//			line configuration extensions ME. (R,-W) (mandatory for Annex-C of [ITUT-G.992.3] and Annex-C of
+//			[ITUT-G.992.5]) (3-*-N bytes, where N is the number of breakpoints)
 //
 type Vdsl2LineConfigurationExtensions2 struct {
 	ManagedEntityDefinition
diff --git a/generated/vdsl2lineconfigurationextensions3.go b/generated/vdsl2lineconfigurationextensions3.go
index e4f244c..fd642d2 100644
--- a/generated/vdsl2lineconfigurationextensions3.go
+++ b/generated/vdsl2lineconfigurationextensions3.go
@@ -27,11 +27,11 @@
 
 // Vdsl2LineConfigurationExtensions3ClassID is the 16-bit ID for the OMCI
 // Managed entity VDSL2 line configuration extensions 3
-const Vdsl2LineConfigurationExtensions3ClassID ClassID = ClassID(410)
+const Vdsl2LineConfigurationExtensions3ClassID = ClassID(410) // 0x019a
 
 var vdsl2lineconfigurationextensions3BME *ManagedEntityDefinition
 
-// Vdsl2LineConfigurationExtensions3 (class ID #410)
+// Vdsl2LineConfigurationExtensions3 (Class ID: #410 / 0x019a)
 //	This ME extends the xDSL line configuration MEs.
 //
 //	An instance of this ME is created and deleted by the OLT.
@@ -43,57 +43,55 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. All xDSL and
-//			VDSL2 line configuration profiles and extensions that pertain to a given PPTP xDSL UNI must
-//			share a common ME ID. (R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. All xDSL and VDSL2 line
+//			configuration profiles and extensions that pertain to a given PPTP xDSL UNI must share a common
+//			ME ID. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Ripolicyds
-//			RIPOLICYds: This attribute indicates which policy shall be applied to determine the triggers for
-//			re-initialization in the downstream direction. A valid range of values is given in clause
+//			This attribute indicates which policy shall be applied to determine the triggers for re-
+//			initialization in the downstream direction. A valid range of values is given in clause
 //			7.3.1.1.12.1 of [ITU-T G.997.1]. (R,-W) (optional) (1-byte)
 //
 //		Ripolicyus
-//			RIPOLICYus: This attribute indicates which policy shall be applied to determine the triggers for
-//			re-initialization in the upstream direction. A valid range of values is given in clause
+//			This attribute indicates which policy shall be applied to determine the triggers for re-
+//			initialization in the upstream direction. A valid range of values is given in clause
 //			7.3.1.1.12.2 of [ITU-T G.997.1]. (R,-W) (optional) (1-byte)
 //
 //		Reinit_Time_Thresholdds
-//			REINIT_TIME_THRESHOLDds: This attribute indicates defines the downstream threshold for re-
-//			initialization based on SES, to be used by the VTU receiver when re-initialization policy 1 is
-//			used in downstream. A valid range of values is given in clause 7.3.1.1.13.1 of [ITU-T G.997.1].
-//			(R,-W) (optional) (1-byte)
+//			This attribute indicates defines the downstream threshold for re-initialization based on SES, to
+//			be used by the VTU receiver when re-initialization policy 1 is used in downstream. A valid range
+//			of values is given in clause 7.3.1.1.13.1 of [ITU-T G.997.1]. (R,-W) (optional) (1-byte)
 //
 //		Reinit_Time_Thresholdus
-//			REINIT_TIME_THRESHOLDus: This attribute indicates defines the upstream threshold for re-
-//			initialization based on SES, to be used by the VTU receiver when reinitialization policy 1 is
-//			used in upstream. A valid range of values is given in clause 7.3.1.1.13.2 of [ITU-T G.997.1].
-//			(R,-W) (optional) (1-byte)
+//			This attribute indicates defines the upstream threshold for re-initialization based on SES, to
+//			be used by the VTU receiver when reinitialization policy 1 is used in upstream. A valid range of
+//			values is given in clause 7.3.1.1.13.2 of [ITU-T G.997.1]. (R,-W) (optional) (1-byte)
 //
 //		Rxrefvnsfus
-//			RXREFVNSFus: If SNRM_MODE = 4, this attribute defines the upstream receiver-referred virtual
-//			noise scaling factor. The attribute value ranges from 0  (-64.0-dBm) to 255 (+63.5-dBm) - see
-//			clause 7.3.1.7.5 of [ITU-T G.997.1]. (R,-W) (optional) (1-byte)
+//			If SNRM_MODE = 4, this attribute defines the upstream receiver-referred virtual noise scaling
+//			factor. The attribute value ranges from 0  (-64.0-dBm) to 255 (+63.5-dBm) - see clause 7.3.1.7.5
+//			of [ITU-T G.997.1]. (R,-W) (optional) (1-byte)
 //
 //		Txrefvnsfds
-//			TXREFVNSFds: If SNRM_MODE = 4, this attribute defines the downstream transmitter referred
-//			virtual noise scaling factor. The attribute value ranges from 0  (-64.0-dBm) to 255 (+63.5-dBm)
-//			- see clause 7.3.1.7.6 of [ITU-T G.997.1]. (R,-W) (optional) (1-byte)
+//			If SNRM_MODE = 4, this attribute defines the downstream transmitter referred virtual noise
+//			scaling factor. The attribute value ranges from 0  (-64.0-dBm) to 255 (+63.5-dBm) - see clause
+//			7.3.1.7.6 of [ITU-T G.997.1]. (R,-W) (optional) (1-byte)
 //
 //		Rtx_Modeds
-//			RTX_MODEds: This attribute controls the mode of operation of [ITU-T G.998.4] retransmission in
-//			the downstream direction. A valid range of values is given in clause 7.3.1.11 of [ITU-T
-//			G.997.1]. (R,-W) (mandatory) (1-byte)
-//
-//		Rtx_Modeus
-//			RTX_MODEus: This attribute controls the mode of operation of [ITU-T G.998.4] retransmission in
-//			the upstream direction. A valid range of values is given in clause 7.3.1.11 of [ITU-T G.997.1].
+//			This attribute controls the mode of operation of [ITU-T G.998.4] retransmission in the
+//			downstream direction. A valid range of values is given in clause 7.3.1.11 of [ITU-T G.997.1].
 //			(R,-W) (mandatory) (1-byte)
 //
+//		Rtx_Modeus
+//			This attribute controls the mode of operation of [ITU-T G.998.4] retransmission in the upstream
+//			direction. A valid range of values is given in clause 7.3.1.11 of [ITU-T G.997.1]. (R,-W)
+//			(mandatory) (1-byte)
+//
 //		Leftr_Thresh
-//			LEFTR_THRESH: If retransmission is used in a given transmit direction, LEFTR_THRESH specifies
-//			the threshold for declaring a near-end ''leftr'' defect. LEFTR_THRESH is equal to the integer
-//			value of this attribute multiplied by 0.01. Valid values and usage are given in clause 7.3.1.12
-//			of [ITU-T G.997.1]. (R,-W) (mandatory) (1-byte)
+//			If retransmission is used in a given transmit direction, LEFTR_THRESH specifies the threshold
+//			for declaring a near-end ''leftr'' defect. LEFTR_THRESH is equal to the integer value of this
+//			attribute multiplied by 0.01. Valid values and usage are given in clause 7.3.1.12 of [ITU-T
+//			G.997.1]. (R,-W) (mandatory) (1-byte)
 //
 //		Maxdelayoctet_Split Parameter Mdosplit
 //			MAXDELAYOCTET-split parameter (MDOSPLIT): This attribute defines the percentage of the
diff --git a/generated/vdsl2lineinventoryandstatusdatapart1.go b/generated/vdsl2lineinventoryandstatusdatapart1.go
index 88dca62..241073c 100644
--- a/generated/vdsl2lineinventoryandstatusdatapart1.go
+++ b/generated/vdsl2lineinventoryandstatusdatapart1.go
@@ -27,11 +27,11 @@
 
 // Vdsl2LineInventoryAndStatusDataPart1ClassID is the 16-bit ID for the OMCI
 // Managed entity VDSL2 line inventory and status data part 1
-const Vdsl2LineInventoryAndStatusDataPart1ClassID ClassID = ClassID(168)
+const Vdsl2LineInventoryAndStatusDataPart1ClassID = ClassID(168) // 0x00a8
 
 var vdsl2lineinventoryandstatusdatapart1BME *ManagedEntityDefinition
 
-// Vdsl2LineInventoryAndStatusDataPart1 (class ID #168)
+// Vdsl2LineInventoryAndStatusDataPart1 (Class ID: #168 / 0x00a8)
 //	This ME extends the xDSL line configuration MEs. The ME name was chosen because its attributes
 //	were initially unique to ITU-T G.993.2 VDSL2. Due to continuing standards development, some
 //	attributes - and therefore this ME - have also become applicable to other Recommendations,
@@ -47,9 +47,8 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP xDSL UNI part 1 ME. (R)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP xDSL UNI part 1 ME. (R) (mandatory) (2-bytes)
 //
 //		Vdsl2 Transmission System Capability Xtu C
 //			VDSL2 transmission system capability xTUC: This attribute extends the xTU-C transmission system
@@ -57,48 +56,105 @@
 //			capabilities. It is defined by bits 57..64 of Table 9.7.12-1. (R) (mandatory) (1-byte)
 //
 //		Vdsl2 Transmission System
-//			VDSL2 transmission system: This attribute reports the transmission system in use. It extends the
-//			xDSL transmission system attribute of the xDSL line inventory and status data part 2 ME with a
-//			byte that includes VDSL2 capabilities currently in use. It is defined by bits 57..64 of Table
-//			9.7.12-1. (R) (mandatory) (1-byte)
+//			This attribute reports the transmission system in use. It extends the xDSL transmission system
+//			attribute of the xDSL line inventory and status data part 2 ME with a byte that includes VDSL2
+//			capabilities currently in use. It is defined by bits 57..64 of Table 9.7.12-1. (R) (mandatory)
+//			(1-byte)
 //
 //		Vdsl2 Profile
+//			This attribute identifies the profile in use. It is a bit map (0 if not allowed, 1 if allowed)
+//			with the following definition:
+//
+//			Bit	Meaning
+//
+//			1 (LSB)	ITU-T G.993.2 profile 8a
+//
+//			2	ITU-T G.993.2 profile 8b
+//
+//			3	ITU-T G.993.2 profile 8c
+//
+//			4	ITU-T G.993.2 profile 8d
+//
+//			5	ITU-T G.993.2 profile 12a
+//
+//			6	ITU-T G.993.2 profile 12b
+//
+//			7	ITU-T G.993.2 profile 17a
+//
+//			8	ITU-T G.993.2 profile 30a
+//
 //			(R) (mandatory) (1-byte)
 //
 //		Vdsl2 Limit Psd Mask And Bandplan
-//			VDSL2 limit PSD mask and bandplan: This attribute defines the limit PSD mask and band plan in
-//			use. It is a bit map as defined by Table 9.7.6-1. (R) (mandatory) (8-bytes)
+//			This attribute defines the limit PSD mask and band plan in use. It is a bit map as defined by
+//			Table 9.7.6-1. (R) (mandatory) (8-bytes)
 //
 //		Vdsl2 Us0 Psd Mask
-//			VDSL2 US0 PSD mask: This attribute defines the US0 PSD mask in use. It is a bit map as defined
-//			by Table 9.7.62. (R) (mandatory) (4-bytes)
+//			This attribute defines the US0 PSD mask in use. It is a bit map as defined by Table 9.7.62. (R)
+//			(mandatory) (4-bytes)
 //
 //		Actsnrmodeds
+//			This attribute indicates whether transmitter-referred virtual noise is active on the line in the
+//			downstream direction.
+//
+//			1	Virtual noise inactive
+//
+//			2	Virtual noise active
+//
 //			(R) (mandatory) (1-byte)
 //
+//			The following four attributes have similar definitions. In each case, valid attribute values are
+//			1, 2, 4, 8. In ADSL applications, the corresponding value is fixed at 1, and therefore need not
+//			be specified. For VDSL2, it is equal to the size of the subcarrier group used to compute these
+//			attributes (see clause-11.4.1 of [ITUT G.993.2]).
+//
 //		Hlingds
-//			HLINGds:	This attribute contains the number of subcarriers per group used to report HLINpsds.
-//			(R) (mandatory) (1-byte)
+//			This attribute contains the number of subcarriers per group used to report HLINpsds. (R)
+//			(mandatory) (1-byte)
 //
 //		Hloggds
-//			HLOGGds:	This attribute contains the number of subcarriers per group used to report HLOGpsds.
-//			(R) (mandatory) (1-byte)
+//			This attribute contains the number of subcarriers per group used to report HLOGpsds. (R)
+//			(mandatory) (1-byte)
 //
 //		Qlngds
-//			QLNGds:	This attribute contains the number of subcarriers per group used to report QLNpsds. (R)
+//			This attribute contains the number of subcarriers per group used to report QLNpsds. (R)
 //			(mandatory) (1-byte)
 //
 //		Snrgds
-//			SNRGds:	This attribute contains the number of subcarriers per group used to report SNRpsds. (R)
+//			This attribute contains the number of subcarriers per group used to report SNRpsds. (R)
 //			(mandatory) (1-byte)
 //
 //		Mrefpsdds Table
+//			The downstream medley reference PSD table contains the set of breakpoints exchanged in the
+//			MREFPSDds fields of the O-PRM message of [ITU-T G.993.2].
+//
+//			The format is similar to that specified for the PSD descriptor in [ITUT-G.993.2]. In [ITU-T
+//			G.993.2], the first byte gives the size of the table, each entry of which is 3-bytes. In the
+//			OMCI definition, the first byte is omitted because the size of the table is known from the
+//			response to the get command.
+//
 //			(R) (mandatory) (3 * N bytes, where N is the number of breakpoints)
 //
 //		Trellisds
+//			0	Trellis not used
+//
+//			1	Trellis used
+//
 //			(R) (mandatory for ITU-T G.993.2 VDSL2, optional for others) (1-byte)
 //
+//			This attribute reports whether trellis coding is in use in the downstream direction.
+//
 //		Actual Rate Adaptation Mode Downstream
+//			The ACT-RA-MODEds attribute indicates the actual active RA mode in the downstream direction.
+//
+//			1	MANUAL
+//
+//			2	AT_INIT
+//
+//			3	DYNAMIC
+//
+//			4	DYNAMIC with SOS ([ITU-T G.993.2] only)
+//
 //			(R) (optional) (1-byte)
 //
 //		Actual Impulse Noise Protection Robust Operations Channel Roc Downstream
@@ -108,9 +164,9 @@
 //			values and usage are given in clause 7.5.1.34.1 of [ITUT-G.997.1]. (R) (optional) (1-byte)
 //
 //		Snr Margin Roc Downstream
-//			SNR margin ROC downstream: The SNRM-ROC-ds attribute reports the actual signal-to-noise margin
-//			of the ROC in the downstream direction. Its value ranges from 0 (-64.0-dB) to 1270 (+63.0-dB).
-//			The special value 0xFFFF indicates that the attribute is out of range. (R) (optional) (2-bytes)
+//			The SNRM-ROC-ds attribute reports the actual signal-to-noise margin of the ROC in the downstream
+//			direction. Its value ranges from 0 (-64.0-dB) to 1270 (+63.0-dB). The special value 0xFFFF
+//			indicates that the attribute is out of range. (R) (optional) (2-bytes)
 //
 type Vdsl2LineInventoryAndStatusDataPart1 struct {
 	ManagedEntityDefinition
diff --git a/generated/vdsl2lineinventoryandstatusdatapart2.go b/generated/vdsl2lineinventoryandstatusdatapart2.go
index b212076..e4cba76 100644
--- a/generated/vdsl2lineinventoryandstatusdatapart2.go
+++ b/generated/vdsl2lineinventoryandstatusdatapart2.go
@@ -27,11 +27,11 @@
 
 // Vdsl2LineInventoryAndStatusDataPart2ClassID is the 16-bit ID for the OMCI
 // Managed entity VDSL2 line inventory and status data part 2
-const Vdsl2LineInventoryAndStatusDataPart2ClassID ClassID = ClassID(169)
+const Vdsl2LineInventoryAndStatusDataPart2ClassID = ClassID(169) // 0x00a9
 
 var vdsl2lineinventoryandstatusdatapart2BME *ManagedEntityDefinition
 
-// Vdsl2LineInventoryAndStatusDataPart2 (class ID #169)
+// Vdsl2LineInventoryAndStatusDataPart2 (Class ID: #169 / 0x00a9)
 //	This ME extends the xDSL line configuration MEs. The ME name was chosen because its attributes
 //	were initially unique to ITU-T G.993.2 VDSL2. Due to continuing standards development, some
 //	attributes - and therefore this ME - have also become applicable to other Recommendations,
@@ -47,9 +47,8 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP xDSL UNI part 1 ME. (R)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP xDSL UNI part 1 ME. (R) (mandatory) (2-bytes)
 //
 //		Vdsl2 Transmission System Capability Xtu_R
 //			VDSL2 transmission system capability xTU-R: This attribute extends the xTU-R transmission system
@@ -57,41 +56,66 @@
 //			capabilities. It is a defined by bits 57..64 of Table 9.7.12-1. (R) (mandatory) (1-byte)
 //
 //		Actsnrmodeus
+//			1	Virtual noise inactive
+//
+//			2	Virtual noise active
+//
 //			(R) (mandatory) (1-byte)
 //
+//			This attribute indicates whether transmitter-referred virtual noise is active on the line in the
+//			upstream direction.
+//
 //		Upbokle
-//			UPBOKLE:	This attribute contains the electrical length estimated by the VTU-O expressed in
-//			decibels at 1-MHz, kl0 (see O-UPDATE in clause 12.3.3.2.1.2 of [ITUT-G.993.2]). This is the
-//			final electrical length that would have been sent from the VTU-O to the VTU-R if the electrical
-//			length were not forced by the OLT. The value lies in the range 0 (0.0-dB) to 1280 (128.0-dB) (R)
-//			(mandatory) (2-bytes)
+//			This attribute contains the electrical length estimated by the VTU-O expressed in decibels at
+//			1-MHz, kl0 (see O-UPDATE in clause 12.3.3.2.1.2 of [ITUT-G.993.2]). This is the final electrical
+//			length that would have been sent from the VTU-O to the VTU-R if the electrical length were not
+//			forced by the OLT. The value lies in the range 0 (0.0-dB) to 1280 (128.0-dB) (R) (mandatory)
+//			(2-bytes)
+//
+//			The following four attributes have similar definitions. In each case, valid attribute values are
+//			1, 2, 4, 8. In ADSL applications, the corresponding value is fixed at 1, and therefore need not
+//			be specified. For VDSL2, it is equal to the size of the subcarrier group used to compute these
+//			attributes (see clause 11.4.1 of [ITUT G.993.2]).
 //
 //		Hlingus
-//			HLINGus:	This attribute is the number of subcarriers per group used to report HLINpsus. (R)
-//			(mandatory) (1-byte)
+//			This attribute is the number of subcarriers per group used to report HLINpsus. (R) (mandatory)
+//			(1-byte)
 //
 //		Hloggus
-//			HLOGGus:	This attribute is the number of subcarriers per group used to report HLOGpsus. (R)
-//			(mandatory) (1-byte)
+//			This attribute is the number of subcarriers per group used to report HLOGpsus. (R) (mandatory)
+//			(1-byte)
 //
 //		Qlngus
-//			QLNGus:	This attribute is the number of subcarriers per group used to report QLNpsus. (R)
-//			(mandatory) (1-byte)
+//			This attribute is the number of subcarriers per group used to report QLNpsus. (R) (mandatory)
+//			(1-byte)
 //
 //		Snrgus
-//			SNRGus:	This attribute is the number of subcarriers per group used to report SNRpsus. (R)
-//			(mandatory) (1-byte)
+//			This attribute is the number of subcarriers per group used to report SNRpsus. (R) (mandatory)
+//			(1-byte)
 //
 //		Mrefpsdus Table
+//			The upstream medley reference PSD attribute contains the set of breakpoints exchanged in the
+//			MREFPSDus fields of the R-PRM message of [ITU-T G.993.2].
+//
+//			The format is similar to that specified for the PSD descriptor in [ITUT-G.993.2]. In [ITU-T
+//			G.993.2], the first byte gives the size of the table, each entry of which is 3-bytes. In the
+//			OMCI definition, the first byte is omitted because the size of the table is known from the
+//			response to the get command.
+//
 //			(R) (mandatory) (3 * N bytes, where N is the number of breakpoints)
 //
 //		Trellisus
+//			This attribute reports whether trellis coding is in use in the upstream direction.
+//
+//			0	Trellis not used
+//
+//			1	Trellis used
+//
 //			(R) (mandatory for ITU-T G.993.2 VDSL2, optional for others) (1-byte)
 //
 //		Actualce
-//			ACTUALCE: This attribute reports the cyclic extension used on the line. It is coded as an
-//			unsigned integer from 2 to 16 in units of N/32 samples, where 2N is the IDFT size. (R)
-//			(mandatory) (1-byte)
+//			This attribute reports the cyclic extension used on the line. It is coded as an unsigned integer
+//			from 2 to 16 in units of N/32 samples, where 2N is the IDFT size. (R) (mandatory) (1-byte)
 //
 //		Upbokle_R
 //			UPBOKLE-R: This attribute contains the electrical length estimated by the VTU-R expressed in
@@ -100,18 +124,28 @@
 //			(2-bytes)
 //
 //		Actual Rate Adaptation Mode Upstream
+//			The ACT-RA-MODEus attribute indicates the actual active RA mode in the upstream direction.
+//
+//			1	MANUAL
+//
+//			2	AT_INIT
+//
+//			3	DYNAMIC
+//
+//			4	DYNAMIC with SOS ([ITU-T G.993.2] only)
+//
 //			(R) (optional) (1-byte)
 //
 //		Actual Impulse Noise Protection Roc Upstream
-//			Actual impulse noise protection ROC upstream: The ACTINP-ROC-us attribute reports the actual INP
-//			of the ROC in the upstream direction expressed in multiples of T4k. The INP of this attribute is
-//			equal to the integer value multiplied by 0.1 symbols. Valid values and usage are given in clause
-//			7.5.1.34.2 of [ITUT-G.997.1]. (R) (optional) (1-byte)
+//			The ACTINP-ROC-us attribute reports the actual INP of the ROC in the upstream direction
+//			expressed in multiples of T4k. The INP of this attribute is equal to the integer value
+//			multiplied by 0.1 symbols. Valid values and usage are given in clause 7.5.1.34.2 of
+//			[ITUT-G.997.1]. (R) (optional) (1-byte)
 //
 //		Snr Margin Roc Upstream
-//			SNR margin ROC upstream: The SNRM-ROC-us attribute reports the actual signal-to-noise margin of
-//			the ROC in the upstream direction. Its value ranges from 0  (-64.0-dB) to 1270 (+63.0-dB). The
-//			special value 0xFFFF indicates that the attribute is out of range. (R) (optional) (2-bytes)
+//			The SNRM-ROC-us attribute reports the actual signal-to-noise margin of the ROC in the upstream
+//			direction. Its value ranges from 0  (-64.0-dB) to 1270 (+63.0-dB). The special value 0xFFFF
+//			indicates that the attribute is out of range. (R) (optional) (2-bytes)
 //
 type Vdsl2LineInventoryAndStatusDataPart2 struct {
 	ManagedEntityDefinition
diff --git a/generated/vdsl2lineinventoryandstatusdatapart3.go b/generated/vdsl2lineinventoryandstatusdatapart3.go
index aeead66..64102aa 100644
--- a/generated/vdsl2lineinventoryandstatusdatapart3.go
+++ b/generated/vdsl2lineinventoryandstatusdatapart3.go
@@ -27,11 +27,11 @@
 
 // Vdsl2LineInventoryAndStatusDataPart3ClassID is the 16-bit ID for the OMCI
 // Managed entity VDSL2 line inventory and status data part 3
-const Vdsl2LineInventoryAndStatusDataPart3ClassID ClassID = ClassID(170)
+const Vdsl2LineInventoryAndStatusDataPart3ClassID = ClassID(170) // 0x00aa
 
 var vdsl2lineinventoryandstatusdatapart3BME *ManagedEntityDefinition
 
-// Vdsl2LineInventoryAndStatusDataPart3 (class ID #170)
+// Vdsl2LineInventoryAndStatusDataPart3 (Class ID: #170 / 0x00aa)
 //	This ME extends the other xDSL line inventory and status data MEs with attributes specific to
 //	VDSL2. This ME contains per-band attributes for both directions. These same attributes are
 //	defined in the xDSL line inventory and status data part 2 ME, but only for a single band. [ITUT
@@ -45,51 +45,110 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP xDSL UNI part 1 ME. (R)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP xDSL UNI part 1 ME. (R) (mandatory) (2-bytes)
+//
+//		Upstream Bands Count
+//			This attribute reports the number of upstream bands. It can be used to filter the upstream
+//			attributes. All upstream attributes are arrays of per-band entries, of which the first upstream
+//			bands count are populated. The contents of the arrays for unused frequency bands are
+//			unspecified. The original attributes were allocated for as many as four upstream bands, US0, 1,
+//			2, 3; optional extended attributes have been added to accommodate the possibility that five
+//			upstream bands may be needed. (R) (mandatory) (1-byte)
+//
+//		Downstream Bands Count
+//			This attribute reports the number of downstream bands. It can be used to filter the downstream
+//			attributes. All downstream attributes are arrays of per-band entries, of which the first
+//			downstream bands count are populated. The contents of the arrays for unused frequency bands are
+//			unspecified. The original attributes were allocated for as many as three downstream bands, DS1,
+//			2, 3; optional extended attributes have been added to accommodate the possibility that five
+//			downstream bands may be needed. (R) (mandatory) (1-byte)
 //
 //		Downstream Line Attenuation Per Band
-//			Downstream line attenuation per band: The LATNds attribute is defined per usable band. It is the
-//			squared magnitude of the channel characteristics function, H(f), averaged over this band, and
-//			measured during loop diagnostic mode and initialization. The exact definition is included in the
-//			relevant xDSL Recommendation. The upstream line attenuation per band ranges from 0 (0.0-dB) to
-//			1270 (+127.0-dB). The special value 0xFFFF indicates that the line attenuation per band is out
-//			of the range to be represented. (R) (mandatory) (3-bands * 2-bytes-=-6-bytes)
+//			The LATNds attribute is defined per usable band. It is the squared magnitude of the channel
+//			characteristics function, H(f), averaged over this band, and measured during loop diagnostic
+//			mode and initialization. The exact definition is included in the relevant xDSL Recommendation.
+//			The upstream line attenuation per band ranges from 0 (0.0-dB) to 1270 (+127.0-dB). The special
+//			value 0xFFFF indicates that the line attenuation per band is out of the range to be represented.
+//			(R) (mandatory) (3-bands * 2-bytes-=-6-bytes)
 //
 //		Upstream Line Attenuation Per Band
-//			Upstream line attenuation per band: The LATNus attribute is defined per usable band. It is the
-//			squared magnitude of the channel characteristics function H(f) averaged over this band, and
-//			measured during loop diagnostic mode and initialization. The exact definition is included in the
-//			relevant xDSL Recommendation. The upstream line attenuation per band ranges from 0 (0.0-dB) to
-//			1270 (+127.0-dB). The special value 0xFFFF indicates that line attenuation per band is out of
-//			range to be represented. (R) (mandatory) (4-bands * 2-bytes-=-8-bytes)
+//			The LATNus attribute is defined per usable band. It is the squared magnitude of the channel
+//			characteristics function H(f) averaged over this band, and measured during loop diagnostic mode
+//			and initialization. The exact definition is included in the relevant xDSL Recommendation. The
+//			upstream line attenuation per band ranges from 0 (0.0-dB) to 1270 (+127.0-dB). The special value
+//			0xFFFF indicates that line attenuation per band is out of range to be represented. (R)
+//			(mandatory) (4-bands * 2-bytes-=-8-bytes)
 //
 //		Downstream Signal Attenuation Per Band
+//			The SATNds attribute is defined per usable band. It is the measured difference in the total
+//			power transmitted in this band by the xTUC and the total power received by the xTUR during loop
+//			diagnostic mode, initialization and showtime. The exact definition is included in the relevant
+//			xDSL Recommendation. The downstream signal attenuation per band ranges from 0 (0.0-dB) to 1270
+//			(+127.0-dB). The special value 0xFFFF indicates that the signal attenuation per band is out of
+//			the range to be represented. (R) (mandatory) (3 bands * 2-bytes-=-6-bytes)
+//
 //			NOTE 1 - During showtime, only a subset of the subcarriers may be transmitted by the xTU-C, as
 //			compared to loop diagnostic mode and initialization. Therefore, the downstream signal
 //			attenuation value during showtime may be significantly lower than the downstream signal
 //			attenuation value during loop diagnostic mode and initialization.
 //
 //		Upstream Signal Attenuation Per Band
+//			The SATNus attribute is defined per usable band. It is the measured difference in decibels in
+//			the total power transmitted in this band by the xTUR and the total power received in this band
+//			by the xTUC during loop diagnostic mode, initialization and showtime. The exact definition is
+//			included in the relevant xDSL Recommendation. The upstream signal attenuation per band ranges
+//			from 0 (0.0-dB) to 1270 (+127.0-dB). The special value 0xFFFF indicates the signal attenuation
+//			per band is out of range to be represented. (R) (mandatory) (4 bands * 2-bytes-= 8-bytes)
+//
 //			NOTE 2 - During showtime, only a subset of the subcarriers may be transmitted by the xTU-R, as
 //			compared to loop diagnostic mode and initialization. Therefore, the upstream signal attenuation
 //			value during showtime may be significantly lower than the upstream signal attenuation value
 //			during loop diagnostic mode and initialization.
 //
 //		Downstream Snr Margin Per Band
-//			Downstream SNR margin per band: The SNRMpbds attribute is defined per usable band. The
-//			downstream SNR margin per band is the maximum increase of noise power received at the xTU-R,
-//			such that the BER requirements are met for all downstream bearer channels. Each array value
-//			ranges from 0 (-64.0-dB) to 1270 (+63.0-dB). The special value 0xFFFF indicates that the
-//			attribute is out of range to be represented. (R) (mandatory) (3 bands * 2-bytes-=-6-bytes)
+//			The SNRMpbds attribute is defined per usable band. The downstream SNR margin per band is the
+//			maximum increase of noise power received at the xTU-R, such that the BER requirements are met
+//			for all downstream bearer channels. Each array value ranges from 0 (-64.0-dB) to 1270
+//			(+63.0-dB). The special value 0xFFFF indicates that the attribute is out of range to be
+//			represented. (R) (mandatory) (3 bands * 2-bytes-=-6-bytes)
 //
 //		Upstream Snr Margin Per Band
-//			Upstream SNR margin per band: The SNRMpbus attribute is defined per usable band. The upstream
-//			SNR margin per band is the maximum increase of noise power received at the xTU-C, such that the
-//			BER requirements are met for all upstream bearer channels. Each array value ranges from 0
-//			(-64.0-dB) to 1270 (+63.0-dB). The special value 0xFFFF indicates that the attribute is out of
-//			range to be represented. (R) (mandatory) (4 bands * 2-bytes-= 8-bytes)
+//			The SNRMpbus attribute is defined per usable band. The upstream SNR margin per band is the
+//			maximum increase of noise power received at the xTU-C, such that the BER requirements are met
+//			for all upstream bearer channels. Each array value ranges from 0 (-64.0-dB) to 1270 (+63.0-dB).
+//			The special value 0xFFFF indicates that the attribute is out of range to be represented. (R)
+//			(mandatory) (4 bands * 2-bytes-= 8-bytes)
+//
+//		Downstream Line Attenuation Extension
+//			This attribute extends LATNds when more than three downstream bands are used. It is defined in
+//			the same way as the downstream line attenuation per band attribute. (R) (optional) (2 bands *
+//			2-bytes-= 4-bytes)
+//
+//		Upstream Line Attenuation Extension
+//			This attribute extends LATNus when more than four upstream bands are used. It is defined in the
+//			same way as the upstream line attenuation per band attribute. (R) (optional) (1 band *
+//			2-bytes-=-2-bytes)
+//
+//		Downstream Signal Attenuation Extension
+//			This attribute extends SATNds when more than three downstream bands are used. It is defined in
+//			the same way as the downstream signal attenuation per band attribute. (R) (optional) (2 bands *
+//			2-bytes-= 4-bytes)
+//
+//		Upstream Signal Attenuation Extension
+//			This attribute extends SATNus when more than four upstream bands are used. It is defined in the
+//			same way as the upstream signal attenuation per band attribute. (R) (optional) (1 band *
+//			2-bytes-= 2-bytes)
+//
+//		Downstream Snr Margin Extension
+//			This attribute extends SNRMpbds when more than three downstream bands are used. It is defined in
+//			the same way as the downstream SNR margin per band attribute. (R) (optional) (2 bands *
+//			2-bytes-= 4-bytes)
+//
+//		Upstream Snr Margin Extension
+//			This attribute extends SNRMpbus when more than four upstream bands are used. It is defined in
+//			the same way as the upstream SNR margin per band attribute. (R) (optional) (1-band * 2-bytes-=
+//			2-bytes)
 //
 type Vdsl2LineInventoryAndStatusDataPart3 struct {
 	ManagedEntityDefinition
@@ -103,15 +162,23 @@
 		MessageTypes: mapset.NewSetWith(
 			Get,
 		),
-		AllowedAttributeMask: 0xfc00,
+		AllowedAttributeMask: 0xfffc,
 		AttributeDefinitions: AttributeDefinitionMap{
-			0: Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read), false, false, false, 0),
-			1: MultiByteField("DownstreamLineAttenuationPerBand", OctetsAttributeType, 0x8000, 3, toOctets("AAAA"), mapset.NewSetWith(Read), false, false, false, 1),
-			2: Uint32Field("UpstreamLineAttenuationPerBand", UnsignedIntegerAttributeType, 0x4000, 0, mapset.NewSetWith(Read), false, false, false, 2),
-			3: MultiByteField("DownstreamSignalAttenuationPerBand", OctetsAttributeType, 0x2000, 3, toOctets("AAAA"), mapset.NewSetWith(Read), false, false, false, 3),
-			4: Uint32Field("UpstreamSignalAttenuationPerBand", UnsignedIntegerAttributeType, 0x1000, 0, mapset.NewSetWith(Read), false, false, false, 4),
-			5: MultiByteField("DownstreamSnrMarginPerBand", OctetsAttributeType, 0x0800, 3, toOctets("AAAA"), mapset.NewSetWith(Read), false, false, false, 5),
-			6: Uint32Field("UpstreamSnrMarginPerBand", UnsignedIntegerAttributeType, 0x0400, 0, mapset.NewSetWith(Read), false, false, false, 6),
+			0:  Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read), false, false, false, 0),
+			1:  ByteField("UpstreamBandsCount", UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read), false, false, false, 1),
+			2:  ByteField("DownstreamBandsCount", UnsignedIntegerAttributeType, 0x4000, 0, mapset.NewSetWith(Read), false, false, false, 2),
+			3:  MultiByteField("DownstreamLineAttenuationPerBand", OctetsAttributeType, 0x2000, 3, toOctets("AAAA"), mapset.NewSetWith(Read), false, false, false, 3),
+			4:  Uint32Field("UpstreamLineAttenuationPerBand", UnsignedIntegerAttributeType, 0x1000, 0, mapset.NewSetWith(Read), false, false, false, 4),
+			5:  MultiByteField("DownstreamSignalAttenuationPerBand", OctetsAttributeType, 0x0800, 3, toOctets("AAAA"), mapset.NewSetWith(Read), false, false, false, 5),
+			6:  Uint32Field("UpstreamSignalAttenuationPerBand", UnsignedIntegerAttributeType, 0x0400, 0, mapset.NewSetWith(Read), false, false, false, 6),
+			7:  MultiByteField("DownstreamSnrMarginPerBand", OctetsAttributeType, 0x0200, 3, toOctets("AAAA"), mapset.NewSetWith(Read), false, false, false, 7),
+			8:  Uint32Field("UpstreamSnrMarginPerBand", UnsignedIntegerAttributeType, 0x0100, 0, mapset.NewSetWith(Read), false, false, false, 8),
+			9:  Uint16Field("DownstreamLineAttenuationExtension", UnsignedIntegerAttributeType, 0x0080, 0, mapset.NewSetWith(Read), false, true, false, 9),
+			10: ByteField("UpstreamLineAttenuationExtension", UnsignedIntegerAttributeType, 0x0040, 0, mapset.NewSetWith(Read), false, true, false, 10),
+			11: Uint16Field("DownstreamSignalAttenuationExtension", UnsignedIntegerAttributeType, 0x0020, 0, mapset.NewSetWith(Read), false, true, false, 11),
+			12: ByteField("UpstreamSignalAttenuationExtension", UnsignedIntegerAttributeType, 0x0010, 0, mapset.NewSetWith(Read), false, true, false, 12),
+			13: Uint16Field("DownstreamSnrMarginExtension", UnsignedIntegerAttributeType, 0x0008, 0, mapset.NewSetWith(Read), false, true, false, 13),
+			14: ByteField("UpstreamSnrMarginExtension", UnsignedIntegerAttributeType, 0x0004, 0, mapset.NewSetWith(Read), false, true, false, 14),
 		},
 		Access:  CreatedByOnu,
 		Support: UnknownSupport,
diff --git a/generated/vdsl2lineinventoryandstatusdatapart4.go b/generated/vdsl2lineinventoryandstatusdatapart4.go
new file mode 100644
index 0000000..107c9c6
--- /dev/null
+++ b/generated/vdsl2lineinventoryandstatusdatapart4.go
@@ -0,0 +1,194 @@
+/*
+ * 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.
+ */
+/*
+ * NOTE: This file was generated, manual edits will be overwritten!
+ *
+ * Generated by 'goCodeGenerator.py':
+ *              https://github.com/cboling/OMCI-parser/README.md
+ */
+
+package generated
+
+import "github.com/deckarep/golang-set"
+
+// Vdsl2LineInventoryAndStatusDataPart4ClassID is the 16-bit ID for the OMCI
+// Managed entity VDSL2 line inventory and status data part 4
+const Vdsl2LineInventoryAndStatusDataPart4ClassID = ClassID(415) // 0x019f
+
+var vdsl2lineinventoryandstatusdatapart4BME *ManagedEntityDefinition
+
+// Vdsl2LineInventoryAndStatusDataPart4 (Class ID: #415 / 0x019f)
+//	This ME extends the other xDSL line inventory and status data MEs with attributes specific to
+//	VDSL2.
+//
+//	Relationships
+//		This is one of the status data MEs associated with an xDSL UNI. It is required only if VDSL2 is
+//		supported by the PPTP. The ONU automatically creates or deletes an instance of this ME upon
+//		creation or deletion of a PPTP xDSL UNI part 1 that supports these attributes.
+//
+//	Attributes
+//		Managed Entity Id
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP xDSL UNI part 1 ME. (R) (mandatory) (2-bytes)
+//
+//		Vtu_O Estimated Upstream Power Back_Off Electrical Length Per Band Upbokle_Pb
+//			VTU-O estimated upstream power back-off electrical length per band (UPBOKLE-pb): This parameter
+//			is a vector of UPBO electrical length per-band estimates for each supported upstream band except
+//			US0, calculated by the VTU-O, based on separate measurements in the supported upstream bands
+//			excluding US0. This parameter is required for the alternative electrical length estimation
+//			method (ELE-M1). Each per-band estimate is represented by 2-bytes, where the estimate is defined
+//			as the integer value multiplied by 0.1-dB. The valid range of values is given in clause
+//			7.5.1.23.3 of [ITU-T G.997.1] (R) (optional) (4 bands- 2-bytes)
+//
+//		Vtu_R Estimated Upstream Power Back_Off Electrical Length Per Band Upbokle_R_Pb
+//			VTU-R estimated upstream power back-off electrical length per band (UPBOKLE-R-pb): This
+//			parameter is a vector of UPBO electrical length per-band estimates for each supported downstream
+//			band, calculated by the VTU-R, based on separate measurements in the supported downstream bands.
+//			This parameter is required for the alternative electrical length estimation method (ELEM1). Each
+//			per-band estimate is represented by 2-bytes, where the estimate is defined as the integer value
+//			multiplied by 0.1-dB. The valid range of values is given in clause 7.5.1.23.4 of [ITU-T G.997.1]
+//			(R) (optional) (3-bands- 2-bytes)
+//
+//		Upbo Downstream Receiver Signal Level Threshold Rxthrshds
+//			UPBO downstream receiver signal level threshold (RXTHRSHds): This parameter reports the
+//			downstream received signal level threshold value used in the alternative electrical length
+//			estimation method (ELE-M1). Valid values range from 0  (-64-dB) to 64 (0 dB). See clause
+//			7.5.1.23.5 of [ITU-T G.997.1] (R) (optional) (1-byte)
+//
+//		Upbo Upstream Receiver Signal Level Threshold Rxthrshus
+//			UPBO upstream receiver signal level threshold (RXTHRSHus): This parameter reports the upstream
+//			received signal level threshold value used in the alternative electrical length estimation
+//			method. Valid values range from 0 (-64 dB) to 64-(0 dB). See clause 7.5.1.23.6 of [ITU-T
+//			G.997.1] (R) (optional) (1-byte)
+//
+//		Actual Alternative Electrical Length Estimation Mod E Act_Aele_Mode
+//			Actual alternative electrical length estimation mode (ACT-AELE-MODE): This parameter reports the
+//			actual AELE-MODE. Valid values are given in clause-7.5.1.23.7 of [ITU-T G.997.1] (R) (optional)
+//			(1-byte)
+//
+//		Actual Downstream Ripolicy Actripolicyds
+//			Actual downstream RIPOLICY (ACTRIPOLICYds): This parameter indicates the actual re-
+//			initialization policy in use in the downstream direction. Valid values are given in clause
+//			7.5.1.40.1 of [ITU-T G.997.1] (R) (optional) (1-byte)
+//
+//		Actual Upstream Ripolicy Actripolicyus
+//			Actual upstream RIPOLICY (ACTRIPOLICYus): This parameter indicates the actual reinitialization
+//			policy in use in the upstream direction. Valid values are given in clause 7.5.1.40.2 of [ITU-T
+//			G.997.1] (R) (optional) (1-byte)
+//
+//		Attndr Actual M Ethod Attndr_Actmethod
+//			ATTNDR actual method (ATTNDR_ACTMETHOD): This parameter indicates the actual ATTNDR Method used
+//			for calculation of the ATTNDR in the downstream and upstream direction. Valid values are given
+//			in clause 7.5.1.41.1 of [ITUT-G.997.1] (R) (optional) (1-byte)
+//
+//		Attndr Downstream A Ctual Impulse Noise Protection Attndr_Actinpds
+//			ATTNDR downstream actual impulse noise protection (ATTNDR_ACTINPds): If retransmission is not
+//			used in the downstream direction, this parameter indicates the actual INP used in the improved
+//			calculation of the ATTNDR in the downstream direction. If retransmission is used in the
+//			downstream direction, this parameter indicates the actual INP against SHINE used in the improved
+//			calculation of the ATTNDR in the downstream direction. The format and usage is identical to that
+//			of the ACTINP attribute defined in the xDSL channel downstream status data ME. See clause
+//			7.5.1.41.2 of [ITU-T G.997.1] (R) (optional) (1-byte)
+//
+//		Attndr Upstream A Ctual Impulse Noise Protection Attndr_Actinpus
+//			ATTNDR upstream actual impulse noise protection (ATTNDR_ACTINPus): If retransmission is not used
+//			in the upstream direction, this parameter indicates the actual INP used in the improved
+//			calculation of the ATTNDR in the upstream direction. If retransmission is used in the upstream
+//			direction, this parameter indicates the actual INP against SHINE used in the improved
+//			calculation of the ATTNDR in the upstream direction. The format and usage is identical to that
+//			of the ACTINP attribute defined in the xDSL channel downstream status data ME. See clause
+//			7.5.1.41.3 of [ITU-T G.997.1] (R) (optional) (1-byte)
+//
+//		Attndr Downstream A Ctual Impulse Noise Protection Against Rein Attndr_Actinp_Reinds
+//			ATTNDR downstream actual impulse noise protection against REIN (ATTNDR_ACTINP_REINds): If
+//			retransmission is used in the downstream direction, this parameter reports the actual INP
+//			against REIN used in the improved calculation of the ATTNDR in the downstream direction. The
+//			format and usage is identical to that of the ACTINP_REIN attribute defined in the xDSL channel
+//			downstream status data ME. See clause 7.5.1.41.4 of [ITU-T G.997.1] (R) (optional) (1-byte)
+//
+//		Attndr Upstream A Ctual Impulse Noise Protection Against Rein Attndr_Actinp_Reinus
+//			ATTNDR upstream actual impulse noise protection against REIN (ATTNDR_ACTINP_REINus): If
+//			retransmission is used in the upstream direction, this parameter reports the actual INP against
+//			REIN used in the improved calculation of the ATTNDR in the upstream direction. The format and
+//			usage is identical to that of the ACTINP_REIN attribute defined in the xDSL channel downstream
+//			status data ME. See clause 7.5.1.41.5 of [ITUT-G.997.1] (R) (optional) (1-byte)
+//
+//		Attndr Downstream Actual Delay Attndr_Actdelayds
+//			ATTNDR downstream actual delay (ATTNDR_ACTDELAYds): This parameter indicates the actual delay
+//			used in the improved calculation of the ATTNDR in the downstream direction. The delay of this
+//			attribute is equal to the integer value multiplied by 0.1-ms. Valid values are given in clause
+//			7.5.1.41.6 of [ITUT G.997.1] (R) (optional) (1-byte)
+//
+//		Attndr Upstream A Ctual Delay Attndr_Actdelayus
+//			ATTNDR upstream actual delay (ATTNDR_ACTDELAYus): This parameter indicates the actual delay used
+//			in the improved calculation of the ATTNDR in the upstream direction. The delay of this attribute
+//			is equal to the integer value multiplied by 0.1-ms. Valid values are given in clause 7.5.1.41.7
+//			of [ITUT-G.997.1] (R) (optional) (1-byte)
+//
+//		Near_End A Ggregate Achievable Net Data Rate Aggachndr_Ne
+//			Near-end aggregate achievable net data rate (AGGACHNDR_NE): This parameter reports the aggregate
+//			achievable net data rate of the VTU-O, in bits per second. See clause 7.5.1.42.1 of [ITU-T
+//			G.997.1] (R) (optional) (4-bytes)
+//
+//		Far_End Aggregate Achievable Net Data Rate Aggachndr_Fe
+//			Far-end aggregate achievable net data rate (AGGACHNDR_FE): This parameter reports the aggregate
+//			achievable net data rate of the VTU-R, in bits per second. See clause-7.5.1.42.2 of [ITU-T
+//			G.997.1] (R) (optional) (4-bytes)
+//
+type Vdsl2LineInventoryAndStatusDataPart4 struct {
+	ManagedEntityDefinition
+	Attributes AttributeValueMap
+}
+
+func init() {
+	vdsl2lineinventoryandstatusdatapart4BME = &ManagedEntityDefinition{
+		Name:    "Vdsl2LineInventoryAndStatusDataPart4",
+		ClassID: 415,
+		MessageTypes: mapset.NewSetWith(
+			Get,
+		),
+		AllowedAttributeMask: 0xffff,
+		AttributeDefinitions: AttributeDefinitionMap{
+			0:  Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read), false, false, false, 0),
+			1:  Uint32Field("VtuOEstimatedUpstreamPowerBackOffElectricalLengthPerBandUpboklePb", UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read), false, true, false, 1),
+			2:  MultiByteField("VtuREstimatedUpstreamPowerBackOffElectricalLengthPerBandUpbokleRPb", OctetsAttributeType, 0x4000, 3, toOctets("AAAA"), mapset.NewSetWith(Read), false, true, false, 2),
+			3:  ByteField("UpboDownstreamReceiverSignalLevelThresholdRxthrshds", UnsignedIntegerAttributeType, 0x2000, 0, mapset.NewSetWith(Read), false, true, false, 3),
+			4:  ByteField("UpboUpstreamReceiverSignalLevelThresholdRxthrshus", UnsignedIntegerAttributeType, 0x1000, 0, mapset.NewSetWith(Read), false, true, false, 4),
+			5:  ByteField("ActualAlternativeElectricalLengthEstimationModEActAeleMode", UnsignedIntegerAttributeType, 0x0800, 0, mapset.NewSetWith(Read), false, true, false, 5),
+			6:  ByteField("ActualDownstreamRipolicyActripolicyds", UnsignedIntegerAttributeType, 0x0400, 0, mapset.NewSetWith(Read), false, true, false, 6),
+			7:  ByteField("ActualUpstreamRipolicyActripolicyus", UnsignedIntegerAttributeType, 0x0200, 0, mapset.NewSetWith(Read), false, true, false, 7),
+			8:  ByteField("AttndrActualMEthodAttndrActmethod", UnsignedIntegerAttributeType, 0x0100, 0, mapset.NewSetWith(Read), false, true, false, 8),
+			9:  ByteField("AttndrDownstreamACtualImpulseNoiseProtectionAttndrActinpds", UnsignedIntegerAttributeType, 0x0080, 0, mapset.NewSetWith(Read), false, true, false, 9),
+			10: ByteField("AttndrUpstreamACtualImpulseNoiseProtectionAttndrActinpus", UnsignedIntegerAttributeType, 0x0040, 0, mapset.NewSetWith(Read), false, true, false, 10),
+			11: ByteField("AttndrDownstreamACtualImpulseNoiseProtectionAgainstReinAttndrActinpReinds", UnsignedIntegerAttributeType, 0x0020, 0, mapset.NewSetWith(Read), false, true, false, 11),
+			12: ByteField("AttndrUpstreamACtualImpulseNoiseProtectionAgainstReinAttndrActinpReinus", UnsignedIntegerAttributeType, 0x0010, 0, mapset.NewSetWith(Read), false, true, false, 12),
+			13: ByteField("AttndrDownstreamActualDelayAttndrActdelayds", UnsignedIntegerAttributeType, 0x0008, 0, mapset.NewSetWith(Read), false, true, false, 13),
+			14: ByteField("AttndrUpstreamACtualDelayAttndrActdelayus", UnsignedIntegerAttributeType, 0x0004, 0, mapset.NewSetWith(Read), false, true, false, 14),
+			15: Uint32Field("NearEndAGgregateAchievableNetDataRateAggachndrNe", UnsignedIntegerAttributeType, 0x0002, 0, mapset.NewSetWith(Read), false, true, false, 15),
+			16: Uint32Field("FarEndAggregateAchievableNetDataRateAggachndrFe", UnsignedIntegerAttributeType, 0x0001, 0, mapset.NewSetWith(Read), false, true, false, 16),
+		},
+		Access:  CreatedByOnu,
+		Support: UnknownSupport,
+	}
+}
+
+// NewVdsl2LineInventoryAndStatusDataPart4 (class ID 415) creates the basic
+// Managed Entity definition that is used to validate an ME of this type that
+// is received from or transmitted to the OMCC.
+func NewVdsl2LineInventoryAndStatusDataPart4(params ...ParamData) (*ManagedEntity, OmciErrors) {
+	return NewManagedEntity(*vdsl2lineinventoryandstatusdatapart4BME, params...)
+}
diff --git a/generated/version.go b/generated/version.go
index c59c631..28b318a 100644
--- a/generated/version.go
+++ b/generated/version.go
@@ -46,27 +46,27 @@
 	Versions = append(Versions,
 		VersionInfo{
 			Name:       "parser",
-			Version:    "0.15.11",
-			CreateTime: 1628604119.344936,
-			ItuDocName: "T-REC-G.988-201711-I!!MSW-E.docx",
-			SHA256:     "96ffc8bca6f70175c8e281e87e1cf21662d07a7502ebf595c5c3180a9972b9ac",
+			Version:    "0.15.12",
+			CreateTime: 1630609253.7051146,
+			ItuDocName: "T-REC-G.988-202003-I!Amd3!MSW-E.docx",
+			SHA256:     "084f5265bc090ca882fe45f6844d1ce368c218e52c77795060b7643240885469",
 		})
 
 	Versions = append(Versions,
 		VersionInfo{
 			Name:       "pre-parser",
-			Version:    "0.15.9",
-			CreateTime: 1626359259.9888368,
-			ItuDocName: "T-REC-G.988-201711-I!!MSW-E.docx",
-			SHA256:     "96ffc8bca6f70175c8e281e87e1cf21662d07a7502ebf595c5c3180a9972b9ac",
+			Version:    "0.15.12",
+			CreateTime: 1628800053.665055,
+			ItuDocName: "T-REC-G.988-202003-I!Amd3!MSW-E.docx",
+			SHA256:     "084f5265bc090ca882fe45f6844d1ce368c218e52c77795060b7643240885469",
 		})
 
 	Versions = append(Versions,
 		VersionInfo{
 			Name:       "code-generator",
-			Version:    "0.15.11",
-			CreateTime: 1628606750.5555656,
-			ItuDocName: "T-REC-G.988-201711-I!!MSW-E.docx",
-			SHA256:     "96ffc8bca6f70175c8e281e87e1cf21662d07a7502ebf595c5c3180a9972b9ac",
+			Version:    "0.15.12",
+			CreateTime: 1631115478.0461376,
+			ItuDocName: "T-REC-G.988-202003-I!Amd3!MSW-E.docx",
+			SHA256:     "084f5265bc090ca882fe45f6844d1ce368c218e52c77795060b7643240885469",
 		})
 }
diff --git a/generated/virtualethernetinterfacepoint.go b/generated/virtualethernetinterfacepoint.go
index 4312a19..eb15fd2 100644
--- a/generated/virtualethernetinterfacepoint.go
+++ b/generated/virtualethernetinterfacepoint.go
@@ -27,11 +27,11 @@
 
 // VirtualEthernetInterfacePointClassID is the 16-bit ID for the OMCI
 // Managed entity Virtual Ethernet interface point
-const VirtualEthernetInterfacePointClassID ClassID = ClassID(329)
+const VirtualEthernetInterfacePointClassID = ClassID(329) // 0x0149
 
 var virtualethernetinterfacepointBME *ManagedEntityDefinition
 
-// VirtualEthernetInterfacePoint (class ID #329)
+// VirtualEthernetInterfacePoint (Class ID: #329 / 0x0149)
 //	This ME represents the data plane hand-off point in an ONU to a separate (non-OMCI) management
 //	domain. The VEIP is managed by the OMCI, and is potentially known to the non-OMCI management
 //	domain. One or more Ethernet traffic flows are present at this boundary.
@@ -49,26 +49,26 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. When used
-//			independently of a cardholder and circuit pack, the ONU should assign IDs in the sequence 1, 2,
-//			.... When used in conjunction with a cardholder and circuit pack, this 2 byte number indicates
-//			the physical position of the VEIP. The first byte is the slot ID (defined in clause 9.1.5). The
-//			second byte is the port ID, with the range 1..255. The values 0 and 0xFFFF are reserved. (R)
-//			(mandatory) (2 bytes)
+//			This attribute uniquely identifies each instance of this ME. When used independently of a
+//			cardholder and circuit pack, the ONU should assign IDs in the sequence 1, 2, .... When used in
+//			conjunction with a cardholder and circuit pack, this 2 byte number indicates the physical
+//			position of the VEIP. The first byte is the slot ID (defined in clause 9.1.5). The second byte
+//			is the port ID, with the range 1..255. The values 0 and 0xFFFF are reserved. (R) (mandatory) (2
+//			bytes)
 //
 //		Administrative State
-//			Administrative state: This attribute locks (1) and unlocks (0) the functions performed by this
-//			ME. Administrative state is further described in clause A.1.6. (R,-W) (mandatory) (1-byte)
+//			This attribute locks (1) and unlocks (0) the functions performed by this ME. Administrative
+//			state is further described in clause A.1.6. (R,-W) (mandatory) (1-byte)
 //
 //		Operational State
-//			Operational state: This attribute indicates whether the ME is capable of performing its
-//			function. Valid values are enabled (0) and disabled (1). (R) (optional) (1-byte)
+//			This attribute indicates whether the ME is capable of performing its function. Valid values are
+//			enabled (0) and disabled (1). (R) (optional) (1-byte)
 //
 //		Interdomain Name
-//			Interdomain name: This attribute is a character string that provides an optional way to identify
-//			the VEIP to a non-OMCI management domain. The interface may also be identified by its ME ID,
-//			[b-IANA] assigned port and possibly other ways. If the vendor offers no information in this
-//			attribute, it should be set to a sequence of null bytes. (R,-W) (optional) (25-bytes)
+//			This attribute is a character string that provides an optional way to identify the VEIP to a
+//			non-OMCI management domain. The interface may also be identified by its ME ID,  [b-IANA]
+//			assigned port and possibly other ways. If the vendor offers no information in this attribute, it
+//			should be set to a sequence of null bytes. (R,-W) (optional) (25-bytes)
 //
 //		Tcp_Udp Pointer
 //			TCP/UDP pointer: This attribute points to an instance of the TCP/UDP config data ME, which
@@ -77,12 +77,12 @@
 //			or set to its default, a null pointer. (R,-W) (optional) (2-bytes)
 //
 //		Iana Assigned Port
-//			IANA assigned port: This attribute contains the TCP or UDP port value as assigned by  [b-IANA]
-//			for the management protocol associated with this virtual Ethernet interface. This attribute is
-//			to be regarded as a hint, not as a requirement that management communications use this port; the
-//			actual port and protocol are specified in the associated TCP/UDP config data ME. If no port has
-//			been assigned or if the management protocol is free to be chosen at run-time, this attribute
-//			should be set to 0xFFFF. (R) (mandatory) (2-bytes)
+//			This attribute contains the TCP or UDP port value as assigned by  [b-IANA] for the management
+//			protocol associated with this virtual Ethernet interface. This attribute is to be regarded as a
+//			hint, not as a requirement that management communications use this port; the actual port and
+//			protocol are specified in the associated TCP/UDP config data ME. If no port has been assigned or
+//			if the management protocol is free to be chosen at run-time, this attribute should be set to
+//			0xFFFF. (R) (mandatory) (2-bytes)
 //
 type VirtualEthernetInterfacePoint struct {
 	ManagedEntityDefinition
diff --git a/generated/vlantaggingfilterdata.go b/generated/vlantaggingfilterdata.go
index 186d06b..28d2443 100644
--- a/generated/vlantaggingfilterdata.go
+++ b/generated/vlantaggingfilterdata.go
@@ -27,11 +27,11 @@
 
 // VlanTaggingFilterDataClassID is the 16-bit ID for the OMCI
 // Managed entity VLAN tagging filter data
-const VlanTaggingFilterDataClassID ClassID = ClassID(84)
+const VlanTaggingFilterDataClassID = ClassID(84) // 0x0054
 
 var vlantaggingfilterdataBME *ManagedEntityDefinition
 
-// VlanTaggingFilterData (class ID #84)
+// VlanTaggingFilterData (Class ID: #84 / 0x0054)
 //	This ME organizes data associated with VLAN tagging. Instances of this ME are created and
 //	deleted by the OLT.
 //
@@ -42,23 +42,32 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the MAC bridge port configuration
-//			data ME. (R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the MAC bridge port configuration data ME. (R, setbycreate)
+//			(mandatory) (2-bytes)
 //
 //		Vlan Filter List
-//			VLAN filter list: This attribute is a list of provisioned tag control information (TCI) values
-//			for the bridge port. A TCI, comprising user priority, canonical format indicator (CFI) and
-//			virtual local area network identifier (VID), is represented by 2-bytes. This attribute supports
-//			up to 12 VLAN entries. The first N are valid, where N is given by the number of entries
-//			attribute. (R,-W, setbycreate) (mandatory) (24-bytes)
+//			This attribute is a list of provisioned tag control information (TCI) values for the bridge
+//			port. A TCI, comprising user priority, canonical format indicator (CFI) and virtual local area
+//			network identifier (VID), is represented by 2-bytes. This attribute supports up to 12 VLAN
+//			entries. The first N are valid, where N is given by the number of entries attribute. (R,-W,
+//			setbycreate) (mandatory) (24-bytes)
 //
 //		Forward Operation
+//			When a frame passes through the MAC bridge port, it is processed according to the operation
+//			specified by this attribute, in accordance with Table-9.3.111. Figure 9.3.11-3 illustrates the
+//			treatment of frames according to the provisioned action possibilities. Tagged and untagged
+//			frames are treated separately, but both in accordance with Figure 9.3.11-3. While all forwarding
+//			operations are plausible, only actions 0x10 and 0x12 are necessary to construct a VLAN mapper
+//			and an 802.1p mapper, respectively. (R,-W, setbycreate) (mandatory) (1-byte)
+//
+//			Table 9.3.11-1 contains duplicate entries due to simplification of the original set of actions.
+//
 //			Table 9.3.11-1 and the actions listed are discussed in detail in the following.
 //
 //		Number Of Entries
-//			Number of entries: This attribute specifies the number of valid entries in the VLAN filter list.
-//			(R,-W, setbycreate) (mandatory) (1-byte)
+//			This attribute specifies the number of valid entries in the VLAN filter list. (R,-W,
+//			setbycreate) (mandatory) (1-byte)
 //
 type VlanTaggingFilterData struct {
 	ManagedEntityDefinition
diff --git a/generated/vlantaggingoperationconfigurationdata.go b/generated/vlantaggingoperationconfigurationdata.go
index db6b216..b13a398 100644
--- a/generated/vlantaggingoperationconfigurationdata.go
+++ b/generated/vlantaggingoperationconfigurationdata.go
@@ -27,11 +27,11 @@
 
 // VlanTaggingOperationConfigurationDataClassID is the 16-bit ID for the OMCI
 // Managed entity VLAN tagging operation configuration data
-const VlanTaggingOperationConfigurationDataClassID ClassID = ClassID(78)
+const VlanTaggingOperationConfigurationDataClassID = ClassID(78) // 0x004e
 
 var vlantaggingoperationconfigurationdataBME *ManagedEntityDefinition
 
-// VlanTaggingOperationConfigurationData (class ID #78)
+// VlanTaggingOperationConfigurationData (Class ID: #78 / 0x004e)
 //	This ME organizes data associated with VLAN tagging. Instances of this ME are created and
 //	deleted by the OLT.
 //
@@ -51,29 +51,89 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. When the
-//			optional association type attribute is 0 or undefined, this attribute's value is the same as the
-//			ID of the ME with which this VLAN tagging operation configuration data instance is associated,
-//			which may be either a PPTP Ethernet UNI or an IP host config data or an IPv6 host config data
-//			ME. Otherwise, the value of the ME ID is unconstrained except by the need to be unique. (R, set-
-//			by-create) (mandatory) (2 bytes)
+//			This attribute uniquely identifies each instance of this ME. When the optional association type
+//			attribute is 0 or undefined, this attribute's value is the same as the ID of the ME with which
+//			this VLAN tagging operation configuration data instance is associated, which may be either a
+//			PPTP Ethernet UNI or an IP host config data or an IPv6 host config data ME. Otherwise, the value
+//			of the ME ID is unconstrained except by the need to be unique. (R, set-by-create) (mandatory) (2
+//			bytes)
 //
 //		Upstream Vlan Tagging Operation Mode
+//			This attribute controls upstream VLAN tagging. Valid values are as follows.
+//
+//			0	Upstream frame is sent as is, regardless of tag.
+//
+//			1	The upstream frame is tagged, whether or not the received frame was tagged. A tagged frame's
+//			TCI is overwritten with the upstream VLAN tag TCI value. An untagged frame is prepended with a
+//			tag whose values are taken from the upstream VLAN tag TCI value attribute.
+//
+//			2	A tag is prepended to the upstream frame, whether or not the received frame was tagged. If the
+//			received frame is tagged, a second tag (Q-in-Q) is added to the frame. If the received frame is
+//			not tagged, a tag is attached to the frame. The added tag is defined by the upstream VLAN tag
+//			TCI value attribute.
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Upstream Vlan Tag Tci Value
-//			Upstream VLAN tag TCI value: This attribute specifies the TCI for upstream VLAN tagging. It is
-//			used when the upstream VLAN tagging operation mode is 1 or 2. (R,-W, setbycreate) (mandatory)
-//			(2-bytes)
+//			This attribute specifies the TCI for upstream VLAN tagging. It is used when the upstream VLAN
+//			tagging operation mode is 1 or 2. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Downstream Vlan Tagging Operation Mode
+//			This attribute controls downstream VLAN tagging. Valid values are as follows.
+//
+//			0	Downstream frame is sent as is, regardless of tag.
+//
+//			1	If the received frame is tagged, the outer tag is stripped. An untagged frame is forwarded
+//			unchanged.
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Association Type
+//			This attribute specifies the type of ME that is associated with this VLAN tagging operation
+//			configuration data ME. Values are assigned in accordance with the following list.
+//
+//			0	(Default) Physical path termination point Ethernet UNI (for backward compatibility, may also
+//			be an IP host config data ME; they must not have the same ME ID). The associated ME instance is
+//			implicit; its identifier is the same as that of this VLAN tagging operation configuration data.
+//
+//			1	IP host config data or IPv6 host config data
+//
+//			2	IEEE 802.1p mapper service profile
+//
+//			3	MAC bridge port configuration data
+//
+//			4	Physical path termination point xDSL UNI
+//
+//			5	GEM IW termination point
+//
+//			6	Multicast GEM IW termination point
+//
+//			7	Physical path termination point MoCA UNI
+//
+//			8	Reserved
+//
+//			9	Ethernet flow termination point
+//
+//			10	Physical path termination point Ethernet UNI
+//
+//			11	Virtual Ethernet interface point
+//
+//			12	MPLS pseudowire termination point
+//
+//			13	EFM bonding group
+//
 //			The associated ME instance is identified by the associated ME pointer. (R,-W, setbycreate)
 //			(optional) (1-byte)
 //
 //		Associated Me Pointer
+//			When the association type attribute is non-zero, this attribute points to the ME with which this
+//			VLAN tagging operation configuration data ME is associated. Otherwise, this attribute is
+//			undefined, and the association is implicit through the ME ID. (R,-W, setbycreate) (optional)
+//			(2-bytes)
+//
+//			NOTE 2 - Implicit association is retained for legacy compatibility. Explicit pointers are
+//			preferred for new implementations.
+//
 //			NOTE 3 - When the association type is xDSL, the two MSBs may be used to indicate a bearer
 //			channel.
 //
diff --git a/generated/voiceserviceprofile.go b/generated/voiceserviceprofile.go
index 8569032..63406b8 100644
--- a/generated/voiceserviceprofile.go
+++ b/generated/voiceserviceprofile.go
@@ -27,11 +27,11 @@
 
 // VoiceServiceProfileClassID is the 16-bit ID for the OMCI
 // Managed entity Voice service profile
-const VoiceServiceProfileClassID ClassID = ClassID(58)
+const VoiceServiceProfileClassID = ClassID(58) // 0x003a
 
 var voiceserviceprofileBME *ManagedEntityDefinition
 
-// VoiceServiceProfile (class ID #58)
+// VoiceServiceProfile (Class ID: #58 / 0x003a)
 //	This ME organizes data that describe the voice service functions of the ONU. Instances of this
 //	ME are created and deleted by the OLT.
 //
@@ -41,69 +41,201 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Announcement Type
+//			This attribute specifies the treatment when a subscriber goes off hook but does not attempt a
+//			call within the dial-tone timeout interval. Valid values include the following.
+//
+//			0x01	Silence
+//
+//			0x02	Reorder tone
+//
+//			0x03	Fast busy
+//
+//			0x04	Voice announcement
+//
+//			0xFF	Not specified; ONU is free to make its own choice.
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Jitter Target
-//			Jitter target:	This attribute specifies the target value of the jitter buffer in milliseconds.
-//			The system tries to maintain the jitter buffer at the target value. The value 0 specifies
-//			dynamic jitter buffer sizing. (R,-W, setbycreate) (optional) (2-bytes)
+//			This attribute specifies the target value of the jitter buffer in milliseconds. The system tries
+//			to maintain the jitter buffer at the target value. The value 0 specifies dynamic jitter buffer
+//			sizing. (R,-W, setbycreate) (optional) (2-bytes)
 //
 //		Jitter Buffer Max
-//			Jitter buffer max: This attribute specifies the maximum depth of the jitter buffer associated
-//			with this service in milliseconds. The value 0 specifies that the ONU uses its internal default.
-//			(R,-W, set-by-create) (optional) (2-bytes)
+//			This attribute specifies the maximum depth of the jitter buffer associated with this service in
+//			milliseconds. The value 0 specifies that the ONU uses its internal default. (R,-W, set-by-
+//			create) (optional) (2-bytes)
 //
 //		Echo Cancel Ind
-//			Echo cancel ind: The Boolean value true specifies that echo cancellation is on; false specifies
-//			off. (R,-W, setbycreate) (mandatory) (1-byte)
+//			The Boolean value true specifies that echo cancellation is on; false specifies off. (R,-W,
+//			setbycreate) (mandatory) (1-byte)
 //
 //		Pstn Protocol Variant
-//			PSTN protocol variant: This attribute controls which variant of POTS signalling is used on the
-//			associated UNIs. Its value is equal to the [ITU-T E.164] country code. The value 0 specifies
-//			that the ONU uses its internal default. (R,-W, set-by-create) (optional) (2-bytes)
+//			This attribute controls which variant of POTS signalling is used on the associated UNIs. Its
+//			value is equal to the [ITU-T E.164] country code. The value 0 specifies that the ONU uses its
+//			internal default. (R,-W, set-by-create) (optional) (2-bytes)
 //
 //		Dtmf Digit Levels
-//			DTMF digit levels: This attribute specifies the power level of DTMF digits that may be generated
-//			by the ONU towards the subscriber set. It is a 2s complement value referred to 1-mW at the 0
-//			transmission level point (TLP) (dBm0), with resolution 1-dB. The default value 0x8000 selects
-//			the ONU's internal policy. (R, W, setbycreate) (optional) (2-bytes)
+//			This attribute specifies the power level of DTMF digits that may be generated by the ONU towards
+//			the subscriber set. It is a 2s complement value referred to 1-mW at the 0 transmission level
+//			point (TLP) (dBm0), with resolution 1-dB. The default value 0x8000 selects the ONU's internal
+//			policy. (R, W, setbycreate) (optional) (2-bytes)
 //
 //		Dtmf Digit Duration
-//			DTMF digit duration: This attribute specifies the duration of DTMF digits that may be generated
-//			by the ONU towards the subscriber set. It is specified in milliseconds. The default value 0
-//			selects the ONU's internal policy. (R, W, setbycreate) (optional) (2 bytes)
+//			This attribute specifies the duration of DTMF digits that may be generated by the ONU towards
+//			the subscriber set. It is specified in milliseconds. The default value 0 selects the ONU's
+//			internal policy. (R, W, setbycreate) (optional) (2 bytes)
 //
 //		Hook Flash Minimum Time
-//			Hook flash minimum time: This attribute defines the minimum duration recognized by the ONU as a
-//			switchhook flash. It is expressed in milliseconds; the default value 0 selects the ONU's
-//			internal policy. (R, W, setbycreate) (optional) (2 bytes)
+//			This attribute defines the minimum duration recognized by the ONU as a switchhook flash. It is
+//			expressed in milliseconds; the default value 0 selects the ONU's internal policy. (R, W,
+//			setbycreate) (optional) (2 bytes)
 //
 //		Hook Flash Maximum Time
-//			Hook flash maximum time: This attribute defines the maximum duration recognized by the ONU as a
-//			switchhook flash. It is expressed in milliseconds; the default value 0 selects the ONU's
-//			internal policy. (R, W, setbycreate) (optional) (2 bytes)
+//			This attribute defines the maximum duration recognized by the ONU as a switchhook flash. It is
+//			expressed in milliseconds; the default value 0 selects the ONU's internal policy. (R, W,
+//			setbycreate) (optional) (2 bytes)
 //
 //		Tone Pattern Table
+//			This attribute is a table, each of whose entries specifies a complex tone (or silence) and a
+//			duration. By linking tones and silence together, possibly cyclically, continuous, varying or
+//			interrupted tone sequences, repetitive or not, may be defined. A tone sequence is initiated by
+//			pointing to the first tone pattern table entry that defines its parameters. Each entry is a
+//			vector comprising the following components.
+//
+//			Index (1 byte): This component is simply an index into the table. It ranges from 1..255. In a
+//			set operation, the value 0 in this field clears the table.
+//
+//			Tone on (1 byte): This Boolean component controls whether the tone is on (true) or off. If the
+//			tone is off, the frequency and power fields are not meaningful.
+//
+//			Frequency 1 (2 bytes): This component specifies the frequency of one of the tone components in
+//			hertz.
+//
+//			Power 1 (1 byte): This component specifies the power level of the corresponding frequency
+//			component. It ranges from 0 (coded as 0) to  -25.5 (coded as 255)-dBm0 with 0.1-dB resolution.
+//
+//			Three additional pairs of frequency-power components may be specified to define a complex tone.
+//			If a pair of possibilities is not to be used, its frequency field should be set to 0.
+//
+//			Frequency 2 (2 bytes)
+//
+//			Power 2 (1 byte)
+//
+//			Frequency 3 (2 bytes)
+//
+//			Power 3 (1 byte)
+//
+//			Frequency 4 (2 bytes)
+//
+//			Power 4 (1 byte)
+//
+//			The following pair of frequency-power components allows the composite tone to be modulated
+//			(warble effect). If this effect is not to be used, the frequency should be set to 0.
+//
+//			Modulation frequency (2 bytes), hertz
+//
+//			Modulation power (1 byte), 0..25.5-dBm0
+//
+//			Duration (2 bytes): This component specifies the duration of the phase, in milliseconds. The
+//			value 0 specifies that the phase endures indefinitely, i.e., until terminated by other events
+//			such as call abandonment.
+//
+//			Next entry (1 byte): This component is a pointer to another entry in this same table, which
+//			permits sequences of tones to be defined, possibly cyclically. A reference to a non-existent
+//			table entry, or the value 0, indicates that the sequence should be terminated.
+//
 //			(R,-W) (optional) (N * 20 bytes)
 //
 //		Tone Event Table
+//			This attribute is a table, each of whose entries specifies an event for which a tone is defined.
+//			If the tone can be synthesized by a sequence of complex tones and silence, the event refers to
+//			an entry in the tone pattern table. Otherwise, the event refers to a file name that is expected
+//			to be recognized by the ONU environment. Each entry in the tone event table is a vector
+//			comprising the following components.
+//
+//			Event (1 byte): This component is an enumeration of the events for which a tone may be defined.
+//			The event component also serves as the index for the table. A set operation to event 0 causes
+//			the table to be cleared.
+//
+//			Tone pattern (1 byte): This component specifies an entry point into the tone pattern table
+//			attribute, to be invoked when the specified event occurs. The value 0 indicates that no tone
+//			from the tone pattern table is to be played.
+//
+//			Tone file (2 bytes): This component points to a large string ME that contains the path and name
+//			of a file containing a codec sequence to be played out. If no file is found after traversing
+//			these links, no tone is played. The behaviour is unspecified if both tone pattern and tone file
+//			are specified.
+//
+//			Tone file repetitions (1 byte): This component specifies the number of times the tone file is to
+//			be repeated. The value 0 means that the file is to be repeated indefinitely until terminated by
+//			some external event such as call abandonment.
+//
+//			Reserved (2 bytes)
+//
 //			(R,-W) (optional) (N * 7 bytes).
 //
 //		Ringing Pattern Table
+//			This attribute is a table, each of whose entries specifies a ringing pattern and a duration. By
+//			linking ringing and silence together, possibly cyclically, continuous or interrupted ringing
+//			sequences, repetitive or not, may be defined. A ringing sequence is initiated by pointing to the
+//			first ringing pattern table entry that defines its parameters. Each entry is a vector comprising
+//			the following components.
+//
+//			Index (1 byte): This component is simply an index into the table. It ranges from 1..255. In a
+//			set operation, the value 0 in this field clears the table.
+//
+//			Ringing on (1 byte): This Boolean component controls whether ringing is on (true) or off during
+//			this interval.
+//
+//			Duration (2 bytes): This component specifies the duration of the ringing phase, in milliseconds.
+//			The value 0 specifies that the phase endures indefinitely, i.e., until terminated by other
+//			events such as call abandonment.
+//
+//			Next entry (1 byte): This component is a pointer to another entry in this same table, which
+//			permits sequences of ringing bursts to be defined, possibly cyclically. A reference to a non-
+//			existent table entry, or the value 0, indicates that the sequence should be terminated.
+//
 //			(R,-W) (optional) (N * 5 bytes).
 //
 //		Ringing Event Table
+//			This attribute is a table, each of whose entries specifies an event for which a ringing sequence
+//			is defined. If the ringing sequence can be generated as a sequence of power ringing and silent
+//			intervals, the event refers to an entry in the ringing pattern table. Otherwise, the event
+//			refers to a file name that is expected to be recognized by the ONU environment. Each entry is a
+//			vector comprising the following components:
+//
+//			Event (1 byte): This component is an enumeration of the events for which a ringing sequence may
+//			be defined. The event component also serves as the index for the table. A set operation with the
+//			value 0 in this field causes the table to be cleared.
+//
+//			Ringing pattern (1 byte): This component specifies an entry point into the ringing pattern table
+//			attribute, to be invoked when the specified event occurs. The value 0 indicates that no ringing
+//			sequence is defined in the ringing pattern table.
+//
+//			Ringing file (2 bytes): This component points to a large string ME that contains the path and
+//			name of a file containing a ring tone to be played out. If no file is found after traversing
+//			these links, no ringing is played. The behaviour is unspecified if both ringing pattern and
+//			ringing file fields are specified.
+//
+//			Ringing file repetitions (1 byte): This component specifies the number of times the ringing file
+//			is to be repeated. The value 0 means that the file is to be repeated indefinitely until
+//			terminated by some external event such as call abandonment.
+//
+//			Ringing text (2 bytes): This component points to a large string ME that contains a text string
+//			to be displayed on the CPE device in conjunction with this event. A null pointer indicates that
+//			no text is to be displayed.
+//
 //			(R,-W) (optional) (N * 7 bytes).
 //
 //		Network Specific Extensions Pointer
-//			Network specific extensions pointer: This attribute points to a network address ME that contains
-//			the path and name of a file containing network specific parameters for the associated UNIs. The
-//			default value for this attribute is 0xFFFF, a null pointer. (R,-W, set-by-create) (optional)
-//			(2-bytes)
+//			This attribute points to a network address ME that contains the path and name of a file
+//			containing network specific parameters for the associated UNIs. The default value for this
+//			attribute is 0xFFFF, a null pointer. (R,-W, set-by-create) (optional) (2-bytes)
 //
 type VoiceServiceProfile struct {
 	ManagedEntityDefinition
diff --git a/generated/voipapplicationserviceprofile.go b/generated/voipapplicationserviceprofile.go
index 04bf025..2eb1fec 100644
--- a/generated/voipapplicationserviceprofile.go
+++ b/generated/voipapplicationserviceprofile.go
@@ -27,11 +27,11 @@
 
 // VoipApplicationServiceProfileClassID is the 16-bit ID for the OMCI
 // Managed entity VoIP application service profile
-const VoipApplicationServiceProfileClassID ClassID = ClassID(146)
+const VoipApplicationServiceProfileClassID = ClassID(146) // 0x0092
 
 var voipapplicationserviceprofileBME *ManagedEntityDefinition
 
-// VoipApplicationServiceProfile (class ID #146)
+// VoipApplicationServiceProfile (Class ID: #146 / 0x0092)
 //	The VoIP application service profile defines attributes of calling features used in conjunction
 //	with a VoIP line service. It is optional for ONUs that support VoIP services. If a non-OMCI
 //	interface is used to manage SIP for VoIP, this ME is unnecessary.
@@ -44,43 +44,125 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			Managed entity ID:-This attribute uniquely identifies each instance of this ME. (R,-setbycreate)
+//			(mandatory) (2 bytes)
 //
 //		Cid Features
-//			The recommended default value is 0x00. (R,-W, setbycreate) (mandatory) (1-byte)
+//			This attribute contains a bit map of caller ID features. Except as noted, the bit value 0
+//			disables the feature; 1 enables it.
+//
+//			0x01	Calling number
+//
+//			0x02	Calling name
+//
+//			0x04	CID blocking (both number and name)
+//
+//			0x08	CID number - Permanent presentation status for number (0 = public, 1 = private)
+//
+//			0x10	CID name - Permanent presentation status for name  (0 = public, 1 = private)
+//
+//			0x20	Anonymous CID blocking (ACR). It may not be possible to support this in the ONU.
+//
+//			0x40..0x80	Not used
+//
+//			The recommended default value is 0x00. (R, W, setbycreate) (mandatory) (1-byte)
 //
 //		Call Waiting Features
 //			The recommended default value is 0x00. (R,-W, setbycreate) (mandatory) (1-byte)
 //
+//			This attribute contains a bit map of call waiting features. The bit value 0 disables the
+//			feature; 1 enables it.
+//
+//			0x01	Call waiting
+//
+//			0x02	Caller ID announcement
+//
+//			0x04..0x80	Not used
+//
 //		Call Progress Or Transfer Features
-//			The recommended default value is 0x0000. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute is a bit map of call processing features. The bit value 0 disables the feature; 1
+//			enables it.
+//
+//			0x0001	3way
+//
+//			0x0002	Call transfer
+//
+//			0x0004	Call hold
+//
+//			0x0008	Call park
+//
+//			0x0010	Do not disturb
+//
+//			0x0020	Flash on emergency service call (flash is to be processed during an emergency service
+//			call)
+//
+//			0x0040	Emergency service originating hold (determines whether call clearing is to be performed
+//			on on-hook during an emergency service call)
+//
+//			0x0080	6way
+//
+//			0x0100..0x8000	Not used
+//
+//			The recommended default value is 0x0000. (R, W, setbycreate) (mandatory) (2-bytes)
 //
 //		Call Presentation Features
+//			This attribute is a bit map of call presentation features. The bit value 0 disables the feature;
+//			1 enables it.
+//
+//			0x0001	Message waiting indication splash ring
+//
+//			0x0002	Message waiting indication special dial tone
+//
+//			0x0004	Message waiting indication visual indication
+//
+//			0x0008	Call forwarding indication
+//
+//			0x0010	DC voltage based visual message waiting indicator (vmwi) (e.g., neon lamp on a phone to
+//			indicate a message waiting).  For backwards compatibility reasons, the value 0x0010 is a
+//			companion value to 0x0004. If an ONU does not support DC voltage vmwi, the ONU uses other
+//			existing vmwi methods. If the ONU supports DC voltage vmwi and needs to apply DC voltage to turn
+//			on the phone lamp (to indicate message waiting), the values 0x0004 and 0x0010 are set.
+//
+//			0x0020..0x8000	Not used
+//
 //			The recommended default value is 0x0000. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Direct Connect Feature
-//			The recommended default value is 0x00. (R,-W, setbycreate) (mandatory) (1-byte)
+//			This attribute is a bit map of characteristics associated with the direct connect feature. The
+//			bit value 0 disables the feature; 1 enables it.
+//
+//			0x01	Direct connect feature enabled
+//
+//			0x02	Dial tone feature delay option
+//
+//			The recommended default value is 0x00. (R, W, setbycreate) (mandatory) (1-byte)
 //
 //		Direct Connect Uri Pointer
-//			Direct connect URI pointer: This attribute points to a network address ME that specifies the URI
-//			of the direct connect. If this attribute is set to a null pointer, no URI is defined. (R,-W,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute points to a network address ME that specifies the URI of the direct connect. If
+//			this attribute is set to a null pointer, no URI is defined. (R, W, setbycreate) (mandatory) (2
+//			bytes)
 //
 //		Bridged Line Agent Uri Pointer
-//			Bridged line agent URI pointer: This attribute points to a network address ME that specifies the
-//			URI of the bridged line agent. If this attribute is set to a null pointer, no URI is defined.
-//			(R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute points to a network address ME that specifies the URI of the bridged line agent.
+//			If this attribute is set to a null pointer, no URI is defined. (R, W, setbycreate) (mandatory)
+//			(2 bytes)
 //
 //		Conference Factory Uri Pointer
-//			Conference factory URI pointer: This attribute points to a network address ME that specifies the
-//			URI of the conference factory. If this attribute is set to a null pointer, no URI is defined.
-//			(R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute points to a network address ME that specifies the URI of the conference factory.
+//			If this attribute is set to a null pointer, no URI is defined. (R, W, setbycreate) (mandatory)
+//			(2 bytes)
 //
-//		Dial Tone Feature Delay_ W Armline Timer New
+//		Dial Tone Feature Delay_Warmline Timer New
 //			Dial tone feature delay/warmline timer (new): This attribute defines the warmline timer/dial
 //			tone feature delay timer (seconds). The default value 0 specifies vendor-specific
-//			implementation. (R,-W) (optional) (2-bytes)
+//			implementation. (R, W) (optional) (2 bytes)
+//
+//		Ip Host Pointer
+//			This attribute points to the IP host config data or IPv6 host config data ME associated with
+//			this VoIP config data ME. This attribute is only relevant when the VoIP configuration method
+//			used attribute of this ME is set to configuration file retrieval (2) OR IETF sipping config
+//			framework (4). Upon instantiation ONU sets this value to NULL (0xFFFF) pointer. (R, W)
+//			(optional) (2 bytes)
 //
 type VoipApplicationServiceProfile struct {
 	ManagedEntityDefinition
@@ -97,18 +179,19 @@
 			Get,
 			Set,
 		),
-		AllowedAttributeMask: 0xff80,
+		AllowedAttributeMask: 0xffc0,
 		AttributeDefinitions: AttributeDefinitionMap{
-			0: Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read, SetByCreate), false, false, false, 0),
-			1: ByteField("CidFeatures", UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 1),
-			2: ByteField("CallWaitingFeatures", UnsignedIntegerAttributeType, 0x4000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 2),
-			3: Uint16Field("CallProgressOrTransferFeatures", UnsignedIntegerAttributeType, 0x2000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 3),
-			4: Uint16Field("CallPresentationFeatures", UnsignedIntegerAttributeType, 0x1000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 4),
-			5: ByteField("DirectConnectFeature", UnsignedIntegerAttributeType, 0x0800, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 5),
-			6: Uint16Field("DirectConnectUriPointer", UnsignedIntegerAttributeType, 0x0400, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 6),
-			7: Uint16Field("BridgedLineAgentUriPointer", UnsignedIntegerAttributeType, 0x0200, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 7),
-			8: Uint16Field("ConferenceFactoryUriPointer", UnsignedIntegerAttributeType, 0x0100, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 8),
-			9: Uint16Field("DialToneFeatureDelayWArmlineTimerNew", UnsignedIntegerAttributeType, 0x0080, 0, mapset.NewSetWith(Read, Write), false, true, false, 9),
+			0:  Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read, SetByCreate), false, false, false, 0),
+			1:  ByteField("CidFeatures", UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 1),
+			2:  ByteField("CallWaitingFeatures", UnsignedIntegerAttributeType, 0x4000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 2),
+			3:  Uint16Field("CallProgressOrTransferFeatures", UnsignedIntegerAttributeType, 0x2000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 3),
+			4:  Uint16Field("CallPresentationFeatures", UnsignedIntegerAttributeType, 0x1000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 4),
+			5:  ByteField("DirectConnectFeature", UnsignedIntegerAttributeType, 0x0800, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 5),
+			6:  Uint16Field("DirectConnectUriPointer", UnsignedIntegerAttributeType, 0x0400, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 6),
+			7:  Uint16Field("BridgedLineAgentUriPointer", UnsignedIntegerAttributeType, 0x0200, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 7),
+			8:  Uint16Field("ConferenceFactoryUriPointer", UnsignedIntegerAttributeType, 0x0100, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 8),
+			9:  Uint16Field("DialToneFeatureDelayWarmlineTimerNew", UnsignedIntegerAttributeType, 0x0080, 0, mapset.NewSetWith(Read, Write), false, true, false, 9),
+			10: Uint16Field("IpHostPointer", UnsignedIntegerAttributeType, 0x0040, 0, mapset.NewSetWith(Read, Write), false, true, false, 10),
 		},
 		Access:  CreatedByOlt,
 		Support: UnknownSupport,
diff --git a/generated/voipconfigdata.go b/generated/voipconfigdata.go
index 9da4493..0e8f60e 100644
--- a/generated/voipconfigdata.go
+++ b/generated/voipconfigdata.go
@@ -27,11 +27,11 @@
 
 // VoipConfigDataClassID is the 16-bit ID for the OMCI
 // Managed entity VoIP config data
-const VoipConfigDataClassID ClassID = ClassID(138)
+const VoipConfigDataClassID = ClassID(138) // 0x008a
 
 var voipconfigdataBME *ManagedEntityDefinition
 
-// VoipConfigData (class ID #138)
+// VoipConfigData (Class ID: #138 / 0x008a)
 //	The VoIP configuration data ME defines the configuration for VoIP in the ONU. The OLT uses this
 //	ME to discover the VoIP signalling protocols and configuration methods supported by this ONU.
 //	The OLT then uses this ME to select the desired signalling protocol and configuration method.
@@ -44,38 +44,107 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. There is only
-//			one instance, number 0. (R) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. There is only one instance, number
+//			0. (R) (mandatory) (2-bytes)
 //
 //		Available Signalling Protocols
+//			This attribute is a bit map that defines the VoIP signalling protocols supported in the ONU. The
+//			bit value 1 specifies that the ONU supports the associated protocol.
+//
+//			1	(LSB)	SIP
+//
+//			2	ITU-T H.248
+//
+//			3	MGCP
+//
 //			(R) (mandatory) (1-byte)
 //
 //		Signalling Protocol Used
+//			0xFF	Selected by non-OMCI management interface
+//
 //			(R,-W) (mandatory) (1-byte)
 //
+//			This attribute specifies the VoIP signalling protocol to use. Only one type of protocol is
+//			allowed at a time. Valid values are:
+//
+//			0	None
+//
+//			1	SIP
+//
+//			2	ITU-T H.248
+//
+//			3	MGCP
+//
 //		Available Voip Configuration Methods
+//			This attribute is a bit map that indicates the capabilities of the ONU with regard to VoIP
+//			service configuration. The bit value 1 specifies that the ONU supports the associated
+//			capability.
+//
+//			1 (LSB)	ONU capable of using the OMCI to configure its VoIP services.
+//
+//			2	ONU capable of working with configuration file retrieval to configure its VoIP services.
+//
+//			3	ONU capable of working with [BBF TR-069] to configure its VoIP services.
+//
+//			4	ONU capable of working with IETF sipping config framework to configure its VoIP services.
+//
 //			Bits 5..24 are reserved by ITU-T. Bits 25..32 are reserved for proprietary vendor configuration
 //			capabilities. (R) (mandatory) (4-bytes)
 //
 //		Voip Configuration Method Used
+//			Specifies which method is used to configure the ONU's VoIP service.
+//
+//			0	Do not configure - ONU default
+//
+//			1	OMCI
+//
+//			2	Configuration file retrieval
+//
+//			3	BBF TR-069
+//
+//			4	IETF sipping config framework
+//
+//			5..240	Reserved by ITU-T
+//
+//			241..255	Reserved for proprietary vendor configuration methods
+//
 //			(R,-W) (mandatory) (1-byte)
 //
 //		Voip Configuration Address Pointer
+//			If this attribute is set to any value other than a null pointer, it points to a network address
+//			ME, which indicates the address of the server to contact using the method indicated in the VoIP
+//			configuration method used attribute. This attribute is only relevant for non-OMCI configuration
+//			methods.
+//
+//			If this attribute is set to a null pointer, no address is defined by this attribute. However,
+//			the address may be defined by other methods, such as deriving it from the ONU identifier
+//			attribute of the IP host config data ME and using a well-known URI schema.
+//
 //			The default value is 0xFFFF (R,-W) (mandatory) (2-bytes)
 //
 //		Voip Configuration State
+//			Indicates the status of the ONU VoIP service.
+//
+//			0	Inactive: configuration retrieval has not been attempted
+//
+//			1	Active: configuration was retrieved
+//
+//			2	Initializing: configuration is now being retrieved
+//
+//			3	Fault: configuration retrieval process failed
+//
 //			Other values are reserved. At ME instantiation, the ONU sets this attribute to 0. (R)
 //			(mandatory) (1-byte)
 //
 //		Retrieve Profile
-//			Retrieve profile: This attribute provides a means by which the ONU may be notified that a new
-//			VoIP profile should be retrieved. By setting this attribute, the OLT triggers the ONU to
-//			retrieve a new profile. The actual value in the set action is ignored because it is the action
-//			of setting that is important. (W) (mandatory) (1-byte)
+//			This attribute provides a means by which the ONU may be notified that a new VoIP profile should
+//			be retrieved. By setting this attribute, the OLT triggers the ONU to retrieve a new profile. The
+//			actual value in the set action is ignored because it is the action of setting that is important.
+//			(W) (mandatory) (1-byte)
 //
 //		Profile Version
-//			Profile version: This attribute is a character string that identifies the version of the last
-//			retrieved profile. (R) (mandatory) (25-bytes)
+//			This attribute is a character string that identifies the version of the last retrieved profile.
+//			(R) (mandatory) (25-bytes)
 //
 type VoipConfigData struct {
 	ManagedEntityDefinition
diff --git a/generated/voipfeatureaccesscodes.go b/generated/voipfeatureaccesscodes.go
index 02394ba..1b8f0ac 100644
--- a/generated/voipfeatureaccesscodes.go
+++ b/generated/voipfeatureaccesscodes.go
@@ -27,11 +27,11 @@
 
 // VoipFeatureAccessCodesClassID is the 16-bit ID for the OMCI
 // Managed entity VoIP feature access codes
-const VoipFeatureAccessCodesClassID ClassID = ClassID(147)
+const VoipFeatureAccessCodesClassID = ClassID(147) // 0x0093
 
 var voipfeatureaccesscodesBME *ManagedEntityDefinition
 
-// VoipFeatureAccessCodes (class ID #147)
+// VoipFeatureAccessCodes (Class ID: #147 / 0x0093)
 //	The VoIP feature access codes ME defines administrable feature access codes for the VoIP
 //	subscriber. It is optional for ONUs that support VoIP services. If a non-OMCI interface is used
 //	to manage VoIP signalling, this ME is unnecessary.
@@ -44,44 +44,47 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R) (mandatory)
-//			(2-bytes)
+//			The remaining attributes are access codes for the features mentioned in their names. Each
+//			attribute is a string of characters from the set {0..9, *, #}, with trailing nulls in any unused
+//			bytes.
+//
+//			This attribute uniquely identifies each instance of this ME. (R) (mandatory) (2-bytes)
 //
 //		Cancel Call Waiting
-//			Cancel call waiting:	(R,-W) (optional) (5-bytes)
+//			(R,-W) (optional) (5-bytes)
 //
 //		Call Hold
-//			Call hold:		(R,-W) (optional) (5-bytes)
+//				(R,-W) (optional) (5-bytes)
 //
 //		Call Park
-//			Call park:		(R,-W) (optional) (5-bytes)
+//				(R,-W) (optional) (5-bytes)
 //
 //		Caller Id Activate
-//			Caller ID activate:	(R,-W) (optional) (5-bytes)
+//			(R,-W) (optional) (5-bytes)
 //
 //		Caller Id Deactivate
-//			Caller ID deactivate:	(R,-W) (optional) (5-bytes)
+//			(R,-W) (optional) (5-bytes)
 //
 //		Do Not Disturb Activation
-//			Do not disturb activation:	(R,-W) (optional) (5-bytes)
+//			(R,-W) (optional) (5-bytes)
 //
 //		Do Not Disturb Deactivation
-//			Do not disturb deactivation:	(R,-W) (optional) (5-bytes)
+//			(R,-W) (optional) (5-bytes)
 //
 //		Do Not Disturb Pin Change
-//			Do not disturb PIN change:	(R,-W) (optional) (5-bytes)
+//			(R,-W) (optional) (5-bytes)
 //
 //		Emergency Service Number
-//			Emergency service number:	(R,-W) (optional) (5-bytes)
+//			(R,-W) (optional) (5-bytes)
 //
 //		Intercom Service
-//			Intercom service:	(R,-W) (optional) (5-bytes)
+//			(R,-W) (optional) (5-bytes)
 //
 //		Unattended_Blind Call Transfer
 //			Unattended/blind call transfer:	(R, W) (optional) (5 bytes)
 //
 //		Attended Call Transfer
-//			Attended call transfer:	(R, W) (optional) (5 bytes)
+//			(R, W) (optional) (5 bytes)
 //
 type VoipFeatureAccessCodes struct {
 	ManagedEntityDefinition
diff --git a/generated/voiplinestatus.go b/generated/voiplinestatus.go
index 214de88..623b83e 100644
--- a/generated/voiplinestatus.go
+++ b/generated/voiplinestatus.go
@@ -27,11 +27,11 @@
 
 // VoipLineStatusClassID is the 16-bit ID for the OMCI
 // Managed entity VoIP line status
-const VoipLineStatusClassID ClassID = ClassID(141)
+const VoipLineStatusClassID = ClassID(141) // 0x008d
 
 var voiplinestatusBME *ManagedEntityDefinition
 
-// VoipLineStatus (class ID #141)
+// VoipLineStatus (Class ID: #141 / 0x008d)
 //	The VoIP line status ME contains line status information for POTS ports using VoIP services. An
 //	ONU that supports VoIP automatically creates or deletes an instance of this ME upon creation or
 //	deletion of a PPTP POTS UNI.
@@ -41,41 +41,167 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP POTS UNI. (R) (mandatory)
-//			(2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP POTS UNI. (R) (mandatory) (2-bytes)
 //
 //		Voip Codec Used
+//			Reports the current codec used for a VoIP POTS port. Valid values are taken from [IETF RFC
+//			3551], and are the same as specified in the codec selection attribute of the VoIP media profile.
+//			This attribute is meaningful only if the VoIP port session type attribute is not idle.
+//
+//			0	PCMU
+//
+//			1	reserved
+//
+//			2	reserved
+//
+//			3	GSM
+//
+//			4	ITU-T G.723
+//
+//			5	DVI4, 8 kHz
+//
+//			6	DVI4, 16 kHz
+//
+//			7	LPC
+//
+//			8	PCMA
+//
+//			9	ITU-T G.722
+//
+//			10	L16, 2 channels
+//
+//			11	L16, 1 channel
+//
+//			12	QCELP
+//
+//			13	CN
+//
+//			14	MPA
+//
+//			15	ITU-T G.728
+//
+//			16	DVI4, 11.025 kHz
+//
+//			17	DVI4, 22.050 kHz
+//
+//			18	ITU-T G.729
+//
 //			(R) (mandatory) (2-bytes)
 //
 //		Voip Voice Server Status
+//			14	Config done
+//
+//			15	Disabled by switch
+//
 //			(R) (mandatory) (1-byte)
 //
+//			Status of the VoIP session for this POTS port:
+//
+//			0	None/initial
+//
+//			1	Registered
+//
+//			2	In session
+//
+//			3	Failed registration - icmp error
+//
+//			4	Failed registration - failed tcp
+//
+//			5	Failed registration - failed authentication
+//
+//			6	Failed registration - timeout
+//
+//			7	Failed registration - server fail code
+//
+//			8	Failed invite - icmp error
+//
+//			9	Failed invite - failed tcp
+//
+//			10	Failed invite - failed authentication
+//
+//			11	Failed invite - timeout
+//
+//			12	Failed invite - server fail code
+//
+//			13	Port not configured
+//
 //		Voip Port Session Type
+//			This attribute reports the current state of a VoIP POTS port session:
+//
+//			0	Idle/none
+//
+//			1	2way
+//
+//			2	3way
+//
+//			3	Fax/modem
+//
+//			4	Telemetry
+//
+//			5	Conference
+//
 //			(R) (mandatory) (1-byte)
 //
 //		Voip Call 1 Packet Period
-//			Voip call 1 packet period: This attribute reports the packet period for the first call on the
-//			VoIP POTS port. The value is defined in milliseconds. (R) (mandatory) (2-bytes)
+//			This attribute reports the packet period for the first call on the VoIP POTS port. The value is
+//			defined in milliseconds. (R) (mandatory) (2-bytes)
 //
 //		Voip Call 2 Packet Period
-//			Voip call 2 packet period: This attribute reports the packet period for the second call on the
-//			VoIP POTS port. The value is defined in milliseconds. (R) (mandatory) (2-bytes)
+//			This attribute reports the packet period for the second call on the VoIP POTS port. The value is
+//			defined in milliseconds. (R) (mandatory) (2-bytes)
 //
 //		Voip Call 1 Dest Addr
-//			Voip call 1 dest addr: This attribute reports the DA for the first call on the VoIP POTS port.
-//			The value is an ASCII string. (R) (mandatory) (25-bytes)
+//			This attribute reports the DA for the first call on the VoIP POTS port. The value is an ASCII
+//			string. (R) (mandatory) (25-bytes)
 //
 //		Voip Call 2 Dest Addr
-//			Voip call 2 dest addr: This attribute reports the DA for the second call on the VoIP POTS port.
-//			The value is an ASCII string. (R) (mandatory) (25-bytes)
+//			This attribute reports the DA for the second call on the VoIP POTS port. The value is an ASCII
+//			string. (R) (mandatory) (25-bytes)
 //
 //		Voip Line State
+//			This attribute reports the state of the POTS line. This attribute may not be meaningful if the
+//			POTS port is administratively locked, is operationally disabled, or is being tested. Code points
+//			are assigned as follows:
+//
+//			0	Idle, on-hook
+//
+//			1	Off-hook dial tone
+//
+//			2 	Dialling
+//
+//			3	Ringing or FSK alerting/data
+//
+//			4	Audible ringback
+//
+//			5	Connecting
+//
+//			6	Connected
+//
+//			7	Disconnecting, audible indication
+//
+//			8	ROH, no tone
+//
+//			9	ROH with tone
+//
+//			10	Unknown or undefined
+//
 //			(R) (optional) (1 byte)
 //
 //		Emergency Call Status
 //			(R) (Optional) (1-byte)
 //
+//			This attribute reports the current state of an emergency call session (when the ONU is the call
+//			originator) on the VoIP POTS port. The ONU determines the presence of an originating emergency
+//			call on the basis of the Emergency service number attribute of the VoIP feature access codes ME.
+//
+//			0--- No emergency call in progress
+//
+//			1--- Emergency call in progress
+//
+//			NOTE - The ONU may also be able to determine the presence of an emergency call on the basis of
+//			other, unspecified information.
+//
 type VoipLineStatus struct {
 	ManagedEntityDefinition
 	Attributes AttributeValueMap
diff --git a/generated/voipmediaprofile.go b/generated/voipmediaprofile.go
index b908a72..e450946 100644
--- a/generated/voipmediaprofile.go
+++ b/generated/voipmediaprofile.go
@@ -27,11 +27,11 @@
 
 // VoipMediaProfileClassID is the 16-bit ID for the OMCI
 // Managed entity VoIP media profile
-const VoipMediaProfileClassID ClassID = ClassID(142)
+const VoipMediaProfileClassID = ClassID(142) // 0x008e
 
 var voipmediaprofileBME *ManagedEntityDefinition
 
-// VoipMediaProfile (class ID #142)
+// VoipMediaProfile (Class ID: #142 / 0x008e)
 //	The VoIP media profile ME contains settings that apply to VoIP voice encoding. This entity is
 //	conditionally required for ONUs that offer VoIP services. If a non-OMCI interface is used to
 //	manage VoIP signalling, this ME is unnecessary.
@@ -44,17 +44,26 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Fax Mode
+//			Selects the fax mode; values are as follows.
+//
+//			0	Passthru
+//
+//			1	ITU-T T.38
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Voice Service Profile Pointer
-//			Voice service profile pointer: Pointer to a voice service profile, which defines parameters such
-//			as jitter buffering and echo cancellation. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			Pointer to a voice service profile, which defines parameters such as jitter buffering and echo
+//			cancellation. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Codec Selection 1st Order
+//			Codec selection (1st order): This attribute specifies codec selection as defined by [IETF-
+//			RFC-3551].
+//
 //			(R,-W, set-by-create) (mandatory) (1-byte)
 //
 //		Packet Period Selection 1st Order
@@ -66,6 +75,9 @@
 //			Silence suppression (1st order): This attribute specifies whether silence suppression is on or
 //			off. Valid values are 0-= off and 1-= on. (R,-W, set-by-create) (mandatory) (1-byte)
 //
+//			Three more groups of three attributes are defined, with definitions identical to the preceding
+//			three:
+//
 //		Codec Selection 2nd Order
 //			Codec selection (2nd order):	(R,-W, setbycreate) (mandatory) (1-byte)
 //
@@ -94,13 +106,13 @@
 //			Silence suppression (4th order):	(R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Oob Dtmf
-//			OOB DTMF:	This attribute specifies out-of-band DMTF carriage. When enabled (1), DTMF signals are
-//			carried out of band via RTP or the associated signalling protocol. When disabled (0), DTMF tones
-//			are carried in the PCM stream. (R,-W, setbycreate) (mandatory) (1-byte)
+//			This attribute specifies out-of-band DMTF carriage. When enabled (1), DTMF signals are carried
+//			out of band via RTP or the associated signalling protocol. When disabled (0), DTMF tones are
+//			carried in the PCM stream. (R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Rtp Profile Pointer
-//			RTP profile pointer: This attribute points to the associated RTP profile data ME. (R,-W,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute points to the associated RTP profile data ME. (R,-W, setbycreate) (mandatory)
+//			(2-bytes)
 //
 type VoipMediaProfile struct {
 	ManagedEntityDefinition
diff --git a/generated/voipvoicectp.go b/generated/voipvoicectp.go
index 2bbd0d7..3dbb0c9 100644
--- a/generated/voipvoicectp.go
+++ b/generated/voipvoicectp.go
@@ -27,11 +27,11 @@
 
 // VoipVoiceCtpClassID is the 16-bit ID for the OMCI
 // Managed entity VoIP voice CTP
-const VoipVoiceCtpClassID ClassID = ClassID(139)
+const VoipVoiceCtpClassID = ClassID(139) // 0x008b
 
 var voipvoicectpBME *ManagedEntityDefinition
 
-// VoipVoiceCtp (class ID #139)
+// VoipVoiceCtp (Class ID: #139 / 0x008b)
 //	The VoIP voice CTP defines the attributes necessary to associate a specified VoIP service (SIP,
 //	ITUT-H.248) with a POTS UNI. This entity is conditionally required for ONUs that offer VoIP
 //	services. If a non-OMCI interface is used to manage VoIP signalling, this ME is unnecessary.
@@ -45,27 +45,41 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		User Protocol Pointer
-//			User protocol pointer: This attribute points to signalling protocol data. If the signalling
-//			protocol used attribute of the VoIP config data ME specifies that the ONU's signalling protocol
-//			is SIP, this attribute points to a SIP user data ME, which in turn points to a SIP agent config
-//			data ME. If the signalling protocol is ITU-T-H.248, this attribute points directly to an MGC
-//			config data ME. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute points to signalling protocol data. If the signalling protocol used attribute of
+//			the VoIP config data ME specifies that the ONU's signalling protocol is SIP, this attribute
+//			points to a SIP user data ME, which in turn points to a SIP agent config data ME. If the
+//			signalling protocol is ITU-T-H.248, this attribute points directly to an MGC config data ME.
+//			(R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Pptp Pointer
-//			PPTP pointer: This attribute points to the PPTP POTS UNI ME that serves the analogue telephone
-//			port. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			This attribute points to the PPTP POTS UNI ME that serves the analogue telephone port. (R,-W,
+//			setbycreate) (mandatory) (2-bytes)
 //
 //		V O Ip Media Profile Pointer
 //			VoIP media profile pointer: This attribute points to an associated VoIP media profile. (R,-W,
 //			setbycreate) (mandatory) (2-bytes)
 //
 //		Signalling Code
+//			3	Loop reverse battery
+//
+//			4	Coin first
+//
+//			5	Dial tone first
+//
+//			6	Multi-party
+//
 //			(R,-W, setbycreate) (mandatory) (1-byte)
 //
+//			This attribute specifies the POTS-side signalling as follows.
+//
+//			1	Loop start
+//
+//			2	Ground start
+//
 type VoipVoiceCtp struct {
 	ManagedEntityDefinition
 	Attributes AttributeValueMap
diff --git a/generated/vpnetworkctp.go b/generated/vpnetworkctp.go
index af565dd..37964fb 100644
--- a/generated/vpnetworkctp.go
+++ b/generated/vpnetworkctp.go
@@ -27,11 +27,11 @@
 
 // VpNetworkCtpClassID is the 16-bit ID for the OMCI
 // Managed entity VP network CTP
-const VpNetworkCtpClassID ClassID = ClassID(269)
+const VpNetworkCtpClassID = ClassID(269) // 0x010d
 
 var vpnetworkctpBME *ManagedEntityDefinition
 
-// VpNetworkCtp (class ID #269)
+// VpNetworkCtp (Class ID: #269 / 0x010d)
 //	NOTE - In [ITU-T G.984.4], this ME is called VP network CTP-G.
 //
 //	This ME represents the termination of VP links on an ONU. It aggregates connectivity
@@ -46,34 +46,32 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
-//			(mandatory) (2-bytes)
-//
-//		Vpi Value
-//			VPI value:	This attribute identifies the VPI value associated with the VP link being terminated.
-//			(R,-W, setbycreate) (mandatory) (2-bytes)
-//
-//		Uni Pointer
-//			UNI pointer: This pointer indicates the xDSL PPTP UNI associated with this VP TP. The bearer
-//			channel may be indicated by the two MSBs of the pointer. (R,-W, setbycreate) (mandatory)
+//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
 //			(2-bytes)
 //
+//		Vpi Value
+//			This attribute identifies the VPI value associated with the VP link being terminated. (R,-W,
+//			setbycreate) (mandatory) (2-bytes)
+//
+//		Uni Pointer
+//			This pointer indicates the xDSL PPTP UNI associated with this VP TP. The bearer channel may be
+//			indicated by the two MSBs of the pointer. (R,-W, setbycreate) (mandatory) (2-bytes)
+//
 //		Direction
-//			Direction:	This attribute specifies whether the VP link is used for UNI-to-ANI (value-1), ANI-
-//			to-UNI (value-2), or bidirectional (value 3) connection. (R,-W, setbycreate) (mandatory)
-//			(1-byte)
+//			This attribute specifies whether the VP link is used for UNI-to-ANI (value-1), ANI-to-UNI
+//			(value-2), or bidirectional (value 3) connection. (R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Deprecated 1
-//			Deprecated 1: Not used; should be set to 0. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			Not used; should be set to 0. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Deprecated 2
-//			Deprecated 2: Not used; should be set to 0. (R,-W, setbycreate) (mandatory) (2-bytes)
+//			Not used; should be set to 0. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Deprecated 3
-//			Deprecated 3: Not used; should be set to 0. (R,-W, setbycreate) (optional) (2-bytes)
+//			Not used; should be set to 0. (R,-W, setbycreate) (optional) (2-bytes)
 //
 //		Deprecated 4
-//			Deprecated 4: Not used; if present, should be set to 0. (R) (optional) (1-byte)
+//			Not used; if present, should be set to 0. (R) (optional) (1-byte)
 //
 type VpNetworkCtp struct {
 	ManagedEntityDefinition
diff --git a/generated/vpperformancemonitoringhistorydata.go b/generated/vpperformancemonitoringhistorydata.go
index 226f563..aaf21f0 100644
--- a/generated/vpperformancemonitoringhistorydata.go
+++ b/generated/vpperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // VpPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity VP performance monitoring history data
-const VpPerformanceMonitoringHistoryDataClassID ClassID = ClassID(62)
+const VpPerformanceMonitoringHistoryDataClassID = ClassID(62) // 0x003e
 
 var vpperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// VpPerformanceMonitoringHistoryData (class ID #62)
+// VpPerformanceMonitoringHistoryData (Class ID: #62 / 0x003e)
 //	This ME collects PM data associated with a VP network CTP. Instances of this ME are created and
 //	deleted by the OLT.
 //
@@ -41,13 +41,11 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the VP network CTP. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the VP network CTP. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -66,8 +64,7 @@
 //			buffer overflows. It records only loss of high priority cells. (R) (mandatory) (2-bytes)
 //
 //		Misinserted Cells
-//			Misinserted cells: This attribute counts cells that are misrouted to a monitored VP. (R)
-//			(mandatory) (2-bytes)
+//			This attribute counts cells that are misrouted to a monitored VP. (R) (mandatory) (2-bytes)
 //
 //		Transmitted C_= 0 _ 1 Cells
 //			Transmitted C-= 0-+ 1 cells: This attribute counts cells originated by the transmitting end
diff --git a/generated/xdslchannelconfigurationprofile.go b/generated/xdslchannelconfigurationprofile.go
index 2b1f36d..a11f3da 100644
--- a/generated/xdslchannelconfigurationprofile.go
+++ b/generated/xdslchannelconfigurationprofile.go
@@ -27,11 +27,11 @@
 
 // XdslChannelConfigurationProfileClassID is the 16-bit ID for the OMCI
 // Managed entity xDSL channel configuration profile
-const XdslChannelConfigurationProfileClassID ClassID = ClassID(107)
+const XdslChannelConfigurationProfileClassID = ClassID(107) // 0x006b
 
 var xdslchannelconfigurationprofileBME *ManagedEntityDefinition
 
-// XdslChannelConfigurationProfile (class ID #107)
+// XdslChannelConfigurationProfile (Class ID: #107 / 0x006b)
 //	This ME contains the channel configuration profile for an xDSL UNI. An instance of this ME is
 //	created and deleted by the OLT.
 //
@@ -45,26 +45,33 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The value 0 is
-//			reserved. (R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. The value 0 is reserved. (R,
+//			setbycreate) (mandatory) (2-bytes)
 //
 //		Minimum Data Rate
-//			Minimum data rate: This parameter specifies the minimum desired net data rate for the bearer
-//			channel. It is coded in bits per second. (R,-W, setbycreate) (mandatory) (4-bytes)
+//			This parameter specifies the minimum desired net data rate for the bearer channel. It is coded
+//			in bits per second. (R,-W, setbycreate) (mandatory) (4-bytes)
 //
 //		Maximum Data Rate
-//			Maximum data rate: This parameter specifies the maximum desired net data rate for the bearer
-//			channel. It is coded in bits per second. (R,-W, setbycreate) (mandatory) (4-bytes)
+//			This parameter specifies the maximum desired net data rate for the bearer channel. It is coded
+//			in bits per second. (R,-W, setbycreate) (mandatory) (4-bytes)
 //
 //		Rate Adaptation Ratio
-//			Rate adaptation ratio: This attribute specifies the weight that should be taken into account
-//			when performing rate adaptation in the direction of the bearer channel. The attribute is defined
-//			as a percentage. The value 20, for example, means that 20% of the available data rate (in excess
-//			of the minimum data rate summed over all bearer channels) is assigned to this bearer channel and
-//			80% to the other bearer channels. The OLT must ensure that the sum of rate adaptation ratios
-//			over all bearers in one direction is 100%. (R,-W, setbycreate) (optional) (1-byte)
+//			This attribute specifies the weight that should be taken into account when performing rate
+//			adaptation in the direction of the bearer channel. The attribute is defined as a percentage. The
+//			value 20, for example, means that 20% of the available data rate (in excess of the minimum data
+//			rate summed over all bearer channels) is assigned to this bearer channel and 80% to the other
+//			bearer channels. The OLT must ensure that the sum of rate adaptation ratios over all bearers in
+//			one direction is 100%. (R,-W, setbycreate) (optional) (1-byte)
 //
 //		Maximum Interleaving Delay
+//			This attribute is the maximum one-way interleaving delay introduced by the PMS-TC between the
+//			alpha and the beta reference points, in the direction of the bearer channel. The one-way
+//			interleaving delay is defined in individual xDSL Recommendations as cap(S*D)-/4-ms, where S is
+//			the S factor, D is the interleaving depth, and cap() denotes rounding to the next higher
+//			integer. xTUs choose S and D values such that the actual one-way interleaving delay does not
+//			exceed the configured maximum interleaving delay.
+//
 //			The delay is coded in milliseconds, varying from 2 to 63, with special meaning assigned to
 //			values 0, 1 and 255. The value 0 indicates that no delay bound is imposed. The value 1 indicates
 //			the fast latency path is to be used in the ITUT G.992.1 operating mode and S and D are to be
@@ -73,26 +80,24 @@
 //			operation. (R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Data Rate Threshold Upshift
-//			Data rate threshold upshift: This attribute is a threshold on the cumulative data rate upshift
-//			achieved over one or more bearer channel data rate adaptations. An upshift rate change (DRT up)
-//			notification is issued by the PPTP xDSL UNI part 1 when the actual data rate exceeds the data
-//			rate at the last entry into showtime by more than the threshold. The data rate threshold is
-//			coded in bits per second. (R,-W, setbycreate) (mandatory for xDSL standards that use this
-//			attribute) (4-bytes)
+//			This attribute is a threshold on the cumulative data rate upshift achieved over one or more
+//			bearer channel data rate adaptations. An upshift rate change (DRT up) notification is issued by
+//			the PPTP xDSL UNI part 1 when the actual data rate exceeds the data rate at the last entry into
+//			showtime by more than the threshold. The data rate threshold is coded in bits per second. (R,-W,
+//			setbycreate) (mandatory for xDSL standards that use this attribute) (4-bytes)
 //
 //		Data Rate Threshold Downshift
-//			Data rate threshold downshift: This attribute is a threshold on the cumulative data rate
-//			downshift achieved over one or more bearer channel data rate adaptations. A downshift rate
-//			change (DRT down) notification is issued by the PPTP xDSL UNI part 1 when the actual data rate
-//			is below the data rate at the last entry into showtime by more than the threshold. The data rate
-//			threshold is coded in bits per second. (R,-W, setbycreate) (mandatory for xDSL standards that
-//			use this attribute) (4-bytes)
+//			This attribute is a threshold on the cumulative data rate downshift achieved over one or more
+//			bearer channel data rate adaptations. A downshift rate change (DRT down) notification is issued
+//			by the PPTP xDSL UNI part 1 when the actual data rate is below the data rate at the last entry
+//			into showtime by more than the threshold. The data rate threshold is coded in bits per second.
+//			(R,-W, setbycreate) (mandatory for xDSL standards that use this attribute) (4-bytes)
 //
 //		Minimum Reserved Data Rate
-//			Minimum reserved data rate: This attribute specifies the desired minimum reserved net data rate
-//			for the bearer channel. The rate is coded in bits per second. This attribute is needed only if
-//			the rate adaptation mode is set to dynamic in the xDSL line configuration profile part 1. (R,-W,
-//			setbycreate) (optional) (4-bytes)
+//			This attribute specifies the desired minimum reserved net data rate for the bearer channel. The
+//			rate is coded in bits per second. This attribute is needed only if the rate adaptation mode is
+//			set to dynamic in the xDSL line configuration profile part 1. (R,-W, setbycreate) (optional)
+//			(4-bytes)
 //
 //		Minimum Data Rate In Low _ Power State
 //			Minimum data rate in low-power state: This parameter specifies the minimum desired net data rate
@@ -101,10 +106,36 @@
 //			in bits per second. (R,-W, setbycreate) (mandatory) (4-byte)
 //
 //		Minimum Impulse Noise Protection
+//			The INPmin attribute specifies the minimum INP for the bearer channel if it is transported over
+//			DMT symbols with a subcarrier spacing of 4.3125-kHz. INP is expressed in DMT symbols with a
+//			subcarrier spacing of 4.3125-kHz. It can be 1/2 symbol or any integer number of symbols from 0
+//			to 16, inclusive.
+//
+//			If the xTU does not support the configured INPmin value, it uses the nearest supported INP value
+//			greater than INPmin.
+//
+//			Value	INPmin
+//
+//			1	0 symbols
+//
+//			2	1/2 symbol
+//
+//			N	(N-- 2) symbols, 3 <= N <= 18
+//
 //			(R,-W, setbycreate) (optional for [ITU-T G.992.1], mandatory for other xDSL standards that use
 //			this attribute) (1-byte)
 //
 //		Maximum Bit Error Ratio
+//			This attribute specifies the desired maximum bit error ratio for the bearer channel. It is only
+//			valid for [ITUT-G.992.3], [ITUT-G.992.4] and [ITUT-G.992.5]. The bit error ratio is specified
+//			via the following values:
+//
+//			1	10-3
+//
+//			2	10-5
+//
+//			3	10-7
+//
 //			(R,-W, setbycreate) (mandatory for standards that use this attribute) (1-byte)
 //
 //		Minimum Impulse Noise Protection 8_Khz
@@ -115,25 +146,24 @@
 //			for [ITUT-G.993.2]) (1 byte)
 //
 //		Maximum Delay Variation
-//			Maximum delay variation: The DVMAX attribute specifies the maximum value for delay variation
-//			allowed in an OLR procedure. Its value ranges from 1 (0.1-ms) to 254 (25.4-ms). The special
-//			value 255 specifies that no delay variation bound is imposed. (R, W) (optional: used by
-//			[ITUT-G.993.2]) (1 byte)
+//			The DVMAX attribute specifies the maximum value for delay variation allowed in an OLR procedure.
+//			Its value ranges from 1 (0.1-ms) to 254 (25.4-ms). The special value 255 specifies that no delay
+//			variation bound is imposed. (R, W) (optional: used by [ITUT-G.993.2]) (1 byte)
 //
 //		Channel Initialization Policy Selection
-//			Channel initialization policy selection: The CIPOLICY attribute specifies the policy to
-//			determine transceiver configuration at initialization. Valid values are 0..1, as defined in the
-//			Recommendations that use this attribute. (R,-W) (optional) (1-byte)
+//			The CIPOLICY attribute specifies the policy to determine transceiver configuration at
+//			initialization. Valid values are 0..1, as defined in the Recommendations that use this
+//			attribute. (R,-W) (optional) (1-byte)
 //
 //		Minimum Sos Bit Rate Downstream
-//			Minimum SOS bit rate downstream: The MIN-SOS-BR-ds attribute specifies the minimum net data rate
-//			required for a valid SOS request in the downstream direction. The value is coded as an unsigned
-//			integer representing the data rate as a multiple of 8-kbit/s. (R,-W) (optional) (4-bytes)
+//			The MIN-SOS-BR-ds attribute specifies the minimum net data rate required for a valid SOS request
+//			in the downstream direction. The value is coded as an unsigned integer representing the data
+//			rate as a multiple of 8-kbit/s. (R,-W) (optional) (4-bytes)
 //
 //		Minimum Sos Bit Rate Upstream
-//			Minimum SOS bit rate upstream: The MIN-SOS-BR-us attribute specifies the minimum net data rate
-//			required for a valid SOS request in the upstream direction. The value is coded as an unsigned
-//			integer representing the data rate as a multiple of 8-kbit/s. (R,-W) (optional) (4-bytes)
+//			The MIN-SOS-BR-us attribute specifies the minimum net data rate required for a valid SOS request
+//			in the upstream direction. The value is coded as an unsigned integer representing the data rate
+//			as a multiple of 8-kbit/s. (R,-W) (optional) (4-bytes)
 //
 type XdslChannelConfigurationProfile struct {
 	ManagedEntityDefinition
diff --git a/generated/xdslchannelconfigurationprofilepart2.go b/generated/xdslchannelconfigurationprofilepart2.go
index ac1aacb..851b056 100644
--- a/generated/xdslchannelconfigurationprofilepart2.go
+++ b/generated/xdslchannelconfigurationprofilepart2.go
@@ -27,11 +27,11 @@
 
 // XdslChannelConfigurationProfilePart2ClassID is the 16-bit ID for the OMCI
 // Managed entity xDSL channel configuration profile part 2
-const XdslChannelConfigurationProfilePart2ClassID ClassID = ClassID(412)
+const XdslChannelConfigurationProfilePart2ClassID = ClassID(412) // 0x019c
 
 var xdslchannelconfigurationprofilepart2BME *ManagedEntityDefinition
 
-// XdslChannelConfigurationProfilePart2 (class ID #412)
+// XdslChannelConfigurationProfilePart2 (Class ID: #412 / 0x019c)
 //	This ME contains the channel configuration profile for an xDSL UNI. An instance of this ME is
 //	created and deleted by the OLT.
 //
@@ -45,9 +45,9 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the xDSL channel configuration
-//			profile. (R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the xDSL channel configuration profile. (R, setbycreate)
+//			(mandatory) (2-bytes)
 //
 //		Minimum Expected Throughput For Retransmission Minetr_Rtx
 //			Minimum expected throughput for retransmission (MINETR_RTX): If retransmission is used in a
@@ -95,10 +95,10 @@
 //			is given in clause 7.3.2.14 of [ITUT-G.997.1]. (R,-W) (mandatory) (1-bytes)
 //
 //		Shineratio_Rtx
-//			SHINERATIO_RTX: If retransmission is used in a given transmit direction, this parameter
-//			specifies the SHINE ratio. This ratio is defined as the integer value of this attribute
-//			multiplied by 0.001. The valid range of values is given in clause-7.3.2.15 of [ITU-T G.997.1].
-//			(R,-W) (mandatory) (1-bytes)
+//			If retransmission is used in a given transmit direction, this parameter specifies the SHINE
+//			ratio. This ratio is defined as the integer value of this attribute multiplied by 0.001. The
+//			valid range of values is given in clause-7.3.2.15 of [ITU-T G.997.1]. (R,-W) (mandatory)
+//			(1-bytes)
 //
 //		Minimum Impulse Noise Protection Against Rein For Retransmission Inpmin_Rein_Rtx
 //			Minimum impulse noise protection against REIN for retransmission (INPMIN_REIN_RTX): If
diff --git a/generated/xdslchanneldownstreamstatusdata.go b/generated/xdslchanneldownstreamstatusdata.go
index 08adc36..172ab1a 100644
--- a/generated/xdslchanneldownstreamstatusdata.go
+++ b/generated/xdslchanneldownstreamstatusdata.go
@@ -27,11 +27,11 @@
 
 // XdslChannelDownstreamStatusDataClassID is the 16-bit ID for the OMCI
 // Managed entity xDSL channel downstream status data
-const XdslChannelDownstreamStatusDataClassID ClassID = ClassID(102)
+const XdslChannelDownstreamStatusDataClassID = ClassID(102) // 0x0066
 
 var xdslchanneldownstreamstatusdataBME *ManagedEntityDefinition
 
-// XdslChannelDownstreamStatusData (class ID #102)
+// XdslChannelDownstreamStatusData (Class ID: #102 / 0x0066)
 //	This ME contains downstream channel status data for an xDSL UNI. The ONU automatically creates
 //	or deletes instances of this ME upon the creation or deletion of a PPTP xDSL UNI part 1.
 //
@@ -43,41 +43,39 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The two MSBs of
-//			the first byte are the bearer channel ID. Excluding the first 2-bits of the first byte, the
-//			remaining part of the ME ID is identical to that of this ME's parent PPTP xDSL UNI part 1. (R)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. The two MSBs of the first byte are
+//			the bearer channel ID. Excluding the first 2-bits of the first byte, the remaining part of the
+//			ME ID is identical to that of this ME's parent PPTP xDSL UNI part 1. (R) (mandatory) (2-bytes)
 //
 //		Actual Interleaving Delay
-//			Actual interleaving delay: This attribute is the actual one-way interleaving delay introduced by
-//			the PMS-TC between the alpha and beta reference points, excluding delay in the L1 and L2 states.
-//			In the L1 and L2 states, the attribute contains the interleaving delay in the previous L0 state.
-//			For ADSL, this attribute is derived from the S and D attributes as cap(S*D)/4 ms, where S is the
-//			number of symbols per codeword, D is the interleaving depth and cap() denotes rounding to the
-//			next higher integer. For [ITU-T G.993.2], this attribute is computed according to the formula in
-//			clause 9.7 of [ITUT-G.993.2]. The actual interleaving delay is coded in milliseconds, rounded to
-//			the nearest millisecond. (R) (mandatory) (1-byte)
+//			This attribute is the actual one-way interleaving delay introduced by the PMS-TC between the
+//			alpha and beta reference points, excluding delay in the L1 and L2 states. In the L1 and L2
+//			states, the attribute contains the interleaving delay in the previous L0 state. For ADSL, this
+//			attribute is derived from the S and D attributes as cap(S*D)/4 ms, where S is the number of
+//			symbols per codeword, D is the interleaving depth and cap() denotes rounding to the next higher
+//			integer. For [ITU-T G.993.2], this attribute is computed according to the formula in clause 9.7
+//			of [ITUT-G.993.2]. The actual interleaving delay is coded in milliseconds, rounded to the
+//			nearest millisecond. (R) (mandatory) (1-byte)
 //
 //		Actual Data Rate
-//			Actual data rate: This parameter reports the actual net data rate of the bearer channel,
-//			excluding the rate in the L1 and L2 states. In the L1 or L2 state, the parameter contains the
-//			net data rate in the previous L0 state. The data rate is coded in bits per second. (R)
-//			(mandatory) (4-bytes)
+//			This parameter reports the actual net data rate of the bearer channel, excluding the rate in the
+//			L1 and L2 states. In the L1 or L2 state, the parameter contains the net data rate in the
+//			previous L0 state. The data rate is coded in bits per second. (R) (mandatory) (4-bytes)
 //
 //		Previous Data Rate
-//			Previous data rate: This parameter reports the previous net data rate of the bearer channel just
-//			before the latest rate change event occurred, excluding transitions between the L0 state and the
-//			L1 or L2 states. A rate change can occur at a power management state transition, e.g., at full
-//			or short initialization, fast retrain or power down, or at a dynamic rate adaptation. The rate
-//			is coded in bits per second (R) (mandatory) (4-bytes)
+//			This parameter reports the previous net data rate of the bearer channel just before the latest
+//			rate change event occurred, excluding transitions between the L0 state and the L1 or L2 states.
+//			A rate change can occur at a power management state transition, e.g., at full or short
+//			initialization, fast retrain or power down, or at a dynamic rate adaptation. The rate is coded
+//			in bits per second (R) (mandatory) (4-bytes)
 //
 //		Actual Impulse Noise Protection
-//			Actual impulse noise protection: The ACTINP attribute reports the actual INP on the bearer
-//			channel in the L0 state. In the L1 or L2 state, the attribute contains the INP in the previous
-//			L0 state. The value of this attribute is a number of DMT symbols, with a granularity of 0.1
-//			symbols. Its range is from 0 (0.0 symbols) to 254 (25.4 symbols). The special value 255
-//			indicates an ACTINP higher than 25.4. (R) (optional for [ITU-T G.992.1], mandatory for other
-//			xDSL Recommendations that support this attribute) (1-byte)
+//			The ACTINP attribute reports the actual INP on the bearer channel in the L0 state. In the L1 or
+//			L2 state, the attribute contains the INP in the previous L0 state. The value of this attribute
+//			is a number of DMT symbols, with a granularity of 0.1 symbols. Its range is from 0 (0.0 symbols)
+//			to 254 (25.4 symbols). The special value 255 indicates an ACTINP higher than 25.4. (R) (optional
+//			for [ITU-T G.992.1], mandatory for other xDSL Recommendations that support this attribute)
+//			(1-byte)
 //
 //		Actual Size Of Reed_Solomon Codeword
 //			Actual size of Reed-Solomon codeword: The NFEC attribute reports the actual Reed-Solomon
@@ -92,30 +90,28 @@
 //			Reed-Solomon coding. (R) (mandatory for ITUT-G.993.2 VDSL2, optional for others) (1-byte)
 //
 //		Actual Number Of Bits Per Symbol
-//			Actual number of bits per symbol: The LSYMB attribute reports the actual number of bits per
-//			symbol assigned to the latency path in which the bearer channel is transported, excluding
-//			trellis overhead. The value is coded in bits, and ranges from 0..65535. (R) (mandatory for [TU-T
-//			G.993.2 VDSL2, optional for others) (2-bytes)
+//			The LSYMB attribute reports the actual number of bits per symbol assigned to the latency path in
+//			which the bearer channel is transported, excluding trellis overhead. The value is coded in bits,
+//			and ranges from 0..65535. (R) (mandatory for [TU-T G.993.2 VDSL2, optional for others) (2-bytes)
 //
 //		Actual Interleaving Depth
-//			Actual interleaving depth: The INTLVDEPTH attribute reports the actual depth of the interleaver
-//			used in the latency path in which the bearer channel is transported. The value ranges from
-//			1..4096 in steps of 1. The value 1 indicates no interleaving. (R) (mandatory for ITU-T G.993.2
-//			VDSL2, optional for others) (2-bytes)
+//			The INTLVDEPTH attribute reports the actual depth of the interleaver used in the latency path in
+//			which the bearer channel is transported. The value ranges from 1..4096 in steps of 1. The value
+//			1 indicates no interleaving. (R) (mandatory for ITU-T G.993.2 VDSL2, optional for others)
+//			(2-bytes)
 //
 //		Actual Interleaving Block Length
-//			Actual interleaving block length: The INTLVBLOCK attribute reports the actual block length of
-//			the interleaver used in the latency path in which the bearer channel is transported. The value
-//			ranges from 4..255 in steps of 1. (R) (mandatory for ITU-T G.993.2 VDSL2, undefined for others)
-//			(1-byte)
+//			The INTLVBLOCK attribute reports the actual block length of the interleaver used in the latency
+//			path in which the bearer channel is transported. The value ranges from 4..255 in steps of 1. (R)
+//			(mandatory for ITU-T G.993.2 VDSL2, undefined for others) (1-byte)
 //
 //		Actual Latency Path
-//			Actual latency path: The LPATH attribute reports the index of the actual latency path in which
-//			the bearer channel is transported. Valid values are 0..3. In [ITUT-G.992.1], the fast path is
-//			mapped to latency index 0; the interleaved path to index 1. (R) (mandatory for ITU-T G.993.2
-//			VDSL2, optional for others) (1-byte)
+//			The LPATH attribute reports the index of the actual latency path in which the bearer channel is
+//			transported. Valid values are 0..3. In [ITUT-G.992.1], the fast path is mapped to latency index
+//			0; the interleaved path to index 1. (R) (mandatory for ITU-T G.993.2 VDSL2, optional for others)
+//			(1-byte)
 //
-//		Actual Impulse Noise Protection Against R Epetitive E Lectrical I Mpulse N Oise Actinp_Rein
+//		Actual Impulse Noise Protection Against Repetitive Electrical Impulse Noise Actinp_Rein
 //			Actual impulse noise protection against repetitive electrical impulse noise (ACTINP_REIN): If
 //			retransmission is used in a given transmit direction, this parameter reports the actual INP
 //			against REIN on the bearer channel. The INP of this attribute is equal to the integer value
@@ -147,7 +143,7 @@
 			8:  Uint16Field("ActualInterleavingDepth", UnsignedIntegerAttributeType, 0x0100, 0, mapset.NewSetWith(Read), false, false, false, 8),
 			9:  ByteField("ActualInterleavingBlockLength", UnsignedIntegerAttributeType, 0x0080, 0, mapset.NewSetWith(Read), false, false, false, 9),
 			10: ByteField("ActualLatencyPath", UnsignedIntegerAttributeType, 0x0040, 0, mapset.NewSetWith(Read), false, false, false, 10),
-			11: ByteField("ActualImpulseNoiseProtectionAgainstREpetitiveELectricalIMpulseNOiseActinpRein", UnsignedIntegerAttributeType, 0x0020, 0, mapset.NewSetWith(Read), false, true, false, 11),
+			11: ByteField("ActualImpulseNoiseProtectionAgainstRepetitiveElectricalImpulseNoiseActinpRein", UnsignedIntegerAttributeType, 0x0020, 0, mapset.NewSetWith(Read), false, true, false, 11),
 		},
 		Access:  CreatedByOnu,
 		Support: UnknownSupport,
diff --git a/generated/xdslchannelupstreamstatusdata.go b/generated/xdslchannelupstreamstatusdata.go
index ed64b7e..58970a7 100644
--- a/generated/xdslchannelupstreamstatusdata.go
+++ b/generated/xdslchannelupstreamstatusdata.go
@@ -27,11 +27,11 @@
 
 // XdslChannelUpstreamStatusDataClassID is the 16-bit ID for the OMCI
 // Managed entity xDSL channel upstream status data
-const XdslChannelUpstreamStatusDataClassID ClassID = ClassID(103)
+const XdslChannelUpstreamStatusDataClassID = ClassID(103) // 0x0067
 
 var xdslchannelupstreamstatusdataBME *ManagedEntityDefinition
 
-// XdslChannelUpstreamStatusData (class ID #103)
+// XdslChannelUpstreamStatusData (Class ID: #103 / 0x0067)
 //	This ME contains upstream channel status data for an xDSL UNI. The ONU automatically creates or
 //	deletes instances of this ME upon the creation or deletion of a PPTP xDSL UNI part 1.
 //
@@ -40,46 +40,44 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The two MSBs of
-//			the first byte are the bearer channel ID. Excluding the first 2-bits of the first byte, the
-//			remaining part of the ME ID is identical to that of this ME's parent PPTP xDSL UNI part 1. (R)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. The two MSBs of the first byte are
+//			the bearer channel ID. Excluding the first 2-bits of the first byte, the remaining part of the
+//			ME ID is identical to that of this ME's parent PPTP xDSL UNI part 1. (R) (mandatory) (2-bytes)
 //
 //		Actual Interleaving Delay
-//			Actual interleaving delay: This attribute is the actual one-way interleaving delay introduced by
-//			the PMS-TC between the alpha and beta reference points, excluding the L1 and L2 states. In the
-//			L1 and L2 states, this attribute contains the interleaving delay in the previous L0 state. For
-//			ADSL, this attribute is derived from the S and D attributes as cap(S*D)/4-ms, where S is the
-//			number of symbols per codeword, D is the interleaving depth and cap() denotes rounding to the
-//			next higher integer. For [ITU-T G.993.2], this attribute is computed according to the formula in
-//			clause 9.7 of [ITUT G.993.2]. The actual interleaving delay is coded in milliseconds, rounded to
-//			the nearest millisecond. (R) (mandatory) (1-byte)
+//			This attribute is the actual one-way interleaving delay introduced by the PMS-TC between the
+//			alpha and beta reference points, excluding the L1 and L2 states. In the L1 and L2 states, this
+//			attribute contains the interleaving delay in the previous L0 state. For ADSL, this attribute is
+//			derived from the S and D attributes as cap(S*D)/4-ms, where S is the number of symbols per
+//			codeword, D is the interleaving depth and cap() denotes rounding to the next higher integer. For
+//			[ITU-T G.993.2], this attribute is computed according to the formula in clause 9.7 of [ITUT
+//			G.993.2]. The actual interleaving delay is coded in milliseconds, rounded to the nearest
+//			millisecond. (R) (mandatory) (1-byte)
 //
 //		Actual Data Rate
-//			Actual data rate: This parameter reports the actual net data rate of the bearer channel,
-//			excluding the L1 and L2 states. In the L1 or L2 state, the parameter contains the net data rate
-//			in the previous L0 state. The data rate is coded in bits per second. (R) (mandatory) (4-bytes)
+//			This parameter reports the actual net data rate of the bearer channel, excluding the L1 and L2
+//			states. In the L1 or L2 state, the parameter contains the net data rate in the previous L0
+//			state. The data rate is coded in bits per second. (R) (mandatory) (4-bytes)
 //
 //		Previous Data Rate
-//			Previous data rate: This parameter reports the previous net data rate of the bearer channel just
-//			before the latest rate change event occurred, excluding transitions between the L0 state and the
-//			L1 or L2 state. A rate change can occur at a power management state transition, e.g., at full or
-//			short initialization, fast retrain or power down, or at a dynamic rate adaptation. The rate is
-//			coded in bits per second. (R) (mandatory) (4-bytes)
+//			This parameter reports the previous net data rate of the bearer channel just before the latest
+//			rate change event occurred, excluding transitions between the L0 state and the L1 or L2 state. A
+//			rate change can occur at a power management state transition, e.g., at full or short
+//			initialization, fast retrain or power down, or at a dynamic rate adaptation. The rate is coded
+//			in bits per second. (R) (mandatory) (4-bytes)
 //
 //		Actual Impulse Noise Protection
-//			Actual impulse noise protection: The ACTINP attribute reports the actual INP on the bearer
-//			channel in the L0 state. In the L1 or L2 state, the attribute contains the INP in the previous
-//			L0 state. The value is coded in fractions of DMT symbols with a granularity of 0.1 symbols. The
-//			range is from 0 (0.0 symbols) to 254 (25.4 symbols). The special value 255 indicates an ACTINP
-//			higher than 25.4. (R) (mandatory for ITU-T G.993.2 VDSL2, optional for other xDSL
-//			Recommendations that support it) (1-byte)
+//			The ACTINP attribute reports the actual INP on the bearer channel in the L0 state. In the L1 or
+//			L2 state, the attribute contains the INP in the previous L0 state. The value is coded in
+//			fractions of DMT symbols with a granularity of 0.1 symbols. The range is from 0 (0.0 symbols) to
+//			254 (25.4 symbols). The special value 255 indicates an ACTINP higher than 25.4. (R) (mandatory
+//			for ITU-T G.993.2 VDSL2, optional for other xDSL Recommendations that support it) (1-byte)
 //
 //		Impulse Noise Protection Reporting Mode
-//			Impulse noise protection reporting mode: The INPREPORT attribute reports the method used to
-//			compute the ACTINP. If set to 0, the ACTINP is computed according to the INP_no_erasure formula
-//			(clause 9.6 of [ITUT G.993.2]). If set to 1, ACTINP is the value estimated by the xTU receiver.
-//			(R) (mandatory for  ITU-T G.993.2 VDSL2) (1-byte)
+//			The INPREPORT attribute reports the method used to compute the ACTINP. If set to 0, the ACTINP
+//			is computed according to the INP_no_erasure formula (clause 9.6 of [ITUT G.993.2]). If set to 1,
+//			ACTINP is the value estimated by the xTU receiver. (R) (mandatory for  ITU-T G.993.2 VDSL2)
+//			(1-byte)
 //
 //		Actual Size Of Reed_Solomon Codeword
 //			Actual size of Reed-Solomon codeword: The NFEC attribute reports the actual Reed-Solomon
@@ -94,28 +92,26 @@
 //			Solomon coding. (R) (mandatory for ITUT-G.993.2 VDSL2, optional for others) (1-byte)
 //
 //		Actual Number Of Bits Per Symbol
-//			Actual number of bits per symbol: The LSYMB attribute reports the actual number of bits per
-//			symbol assigned to the latency path in which the bearer channel is transported, excluding
-//			trellis overhead. Its value is coded in bits in the range 0..65535. (R) (mandatory for
-//			ITUT-G.993.2 VDSL2, optional for others) (2-bytes)
+//			The LSYMB attribute reports the actual number of bits per symbol assigned to the latency path in
+//			which the bearer channel is transported, excluding trellis overhead. Its value is coded in bits
+//			in the range 0..65535. (R) (mandatory for ITUT-G.993.2 VDSL2, optional for others) (2-bytes)
 //
 //		Actual Interleaving Depth
-//			Actual interleaving depth: The INTLVDEPTH attribute reports the actual depth of the interleaver
-//			used in the latency path in which the bearer channel is transported. Its value ranges from
-//			1..4096 in steps of 1. The value 1 indicates no interleaving. (R) (mandatory for ITU-T G.993.2
-//			VDSL2, optional for others) (2-bytes)
+//			The INTLVDEPTH attribute reports the actual depth of the interleaver used in the latency path in
+//			which the bearer channel is transported. Its value ranges from 1..4096 in steps of 1. The value
+//			1 indicates no interleaving. (R) (mandatory for ITU-T G.993.2 VDSL2, optional for others)
+//			(2-bytes)
 //
 //		Actual Interleaving Block Length
-//			Actual interleaving block length: The INTLVBLOCK attribute reports the actual block length of
-//			the interleaver used in the latency part in which the bearer channel is transported. Its value
-//			ranges from 4..255 in steps of 1. (R) (mandatory forITU-T G.993.2 VDSL2, optional for others)
-//			(1-byte)
+//			The INTLVBLOCK attribute reports the actual block length of the interleaver used in the latency
+//			part in which the bearer channel is transported. Its value ranges from 4..255 in steps of 1. (R)
+//			(mandatory forITU-T G.993.2 VDSL2, optional for others) (1-byte)
 //
 //		Actual Latency Path
-//			Actual latency path: The LPATH attribute reports the index of the actual latency path in which
-//			the bearer channel is transported. Valid values are 0..3. In [ITUT-G.992.1], the fast path is
-//			mapped to latency index 0; the interleaved path to index 1. (R) (mandatory for ITU-T G.993.2
-//			VDSL2, optional for others) (1-byte)
+//			The LPATH attribute reports the index of the actual latency path in which the bearer channel is
+//			transported. Valid values are 0..3. In [ITUT-G.992.1], the fast path is mapped to latency index
+//			0; the interleaved path to index 1. (R) (mandatory for ITU-T G.993.2 VDSL2, optional for others)
+//			(1-byte)
 //
 type XdslChannelUpstreamStatusData struct {
 	ManagedEntityDefinition
diff --git a/generated/xdsldownstreamrfibandsprofile.go b/generated/xdsldownstreamrfibandsprofile.go
index 2e017e9..bd31bb0 100644
--- a/generated/xdsldownstreamrfibandsprofile.go
+++ b/generated/xdsldownstreamrfibandsprofile.go
@@ -27,11 +27,11 @@
 
 // XdslDownstreamRfiBandsProfileClassID is the 16-bit ID for the OMCI
 // Managed entity xDSL downstream RFI bands profile
-const XdslDownstreamRfiBandsProfileClassID ClassID = ClassID(111)
+const XdslDownstreamRfiBandsProfileClassID = ClassID(111) // 0x006f
 
 var xdsldownstreamrfibandsprofileBME *ManagedEntityDefinition
 
-// XdslDownstreamRfiBandsProfile (class ID #111)
+// XdslDownstreamRfiBandsProfile (Class ID: #111 / 0x006f)
 //	This ME contains the downstream RFI bands profile for an xDSL UNI. Instances of this ME are
 //	created and deleted by the OLT.
 //
@@ -41,14 +41,55 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The value 0 is
-//			reserved. (R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. The value 0 is reserved. (R,
+//			setbycreate) (mandatory) (2-bytes)
 //
 //		Downstream Rfi Bands Table
+//			The RFIBANDS attribute is a table where each entry comprises:
+//
+//			o	an entry number field (1-byte, first entry numbered 1);
+//
+//			o	subcarrier index 1 field (2-bytes);
+//
+//			o	subcarrier index 2 field (2-bytes).
+//
+//			For [ITU-T G.992.5], this configuration attribute defines the subset of downstream PSD mask
+//			breakpoints, as specified in the downstream PSD mask, to be used to notch an RFI band. This
+//			subset consists of couples of consecutive subcarrier indices belonging to breakpoints: [ti; ti-+
+//			1], corresponding to the low level of the notch. Interpolation around these points is defined in
+//			[ITUT G.992.5].
+//
+//			For [ITU-T G.993.2], this attribute defines the bands where the PSD is to be reduced as
+//			specified in clause 7.2.1.2 of [ITUT G.993.2]. Each band is represented by start and stop
+//			subcarrier indices with a subcarrier spacing of 4.3125-kHz. Up to 16 bands may be specified.
+//			This attribute defines the RFI bands for both upstream and downstream directions.
+//
+//			Entries have the default value 0 for both subcarrier index 1 and subcarrier index-2. Setting an
+//			entry with a non-zero subcarrier index 1 and subcarrier index-2 implies insertion into the table
+//			or replacement of an existing entry. Setting an entry's subcarrier index 1 and subcarrier index
+//			2 to 0 implies deletion from the table, if present.
+//
 //			(R,-W) (mandatory for [ITU-T G.992.5], [ITU-T G.993.2]) (5 * N bytes where N is the number of
 //			RFI bands)
 //
 //		Bands Valid
+//			This Boolean attribute controls and reports the operational status of the downstream RFI bands
+//			table.
+//
+//			If this attribute is true, the downstream RFI bands table has been impressed on the DSL
+//			equipment.
+//
+//			If this attribute is false, the downstream RFI bands table has not been impressed on the DSL
+//			equipment. The default value is false.
+//
+//			This attribute can be modified by the ONU and OLT, as follows.
+//
+//			o	If the OLT changes any of the RFI bands table entries or sets bands valid false, then bands
+//			valid is false.
+//
+//			o	If bands valid is false and OLT sets bands valid true, the ONU impresses the downstream RFI
+//			bands data on to the DSL equipment.
+//
 //			(R,-W) (mandatory) (1-byte)
 //
 type XdslDownstreamRfiBandsProfile struct {
diff --git a/generated/xdslimpulsenoisemonitorperformancemonitoringhistorydata.go b/generated/xdslimpulsenoisemonitorperformancemonitoringhistorydata.go
index 19b15b3..75125b3 100644
--- a/generated/xdslimpulsenoisemonitorperformancemonitoringhistorydata.go
+++ b/generated/xdslimpulsenoisemonitorperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // XdslImpulseNoiseMonitorPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity xDSL impulse noise monitor performance monitoring history data
-const XdslImpulseNoiseMonitorPerformanceMonitoringHistoryDataClassID ClassID = ClassID(324)
+const XdslImpulseNoiseMonitorPerformanceMonitoringHistoryDataClassID = ClassID(324) // 0x0144
 
 var xdslimpulsenoisemonitorperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// XdslImpulseNoiseMonitorPerformanceMonitoringHistoryData (class ID #324)
+// XdslImpulseNoiseMonitorPerformanceMonitoringHistoryData (Class ID: #324 / 0x0144)
 //	This ME collects PM data from the impulse noise monitor function at both near and far ends.
 //	Instances of this ME are created and deleted by the OLT. Note that, unlike most xDSL PM, [ITU-T
 //	G.997.1] only requires current and previous 15-min interval storage; a longer view of this PM is
@@ -45,13 +45,11 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The ME ID is
-//			identical to that of this ME's parent PPTP xDSL UNI part 1. (R, setbycreate) (mandatory)
-//			(2-bytes)
+//			This attribute uniquely identifies each instance of this ME. The ME ID is identical to that of
+//			this ME's parent PPTP xDSL UNI part 1. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: No thresholds are defined for this ME. For uniformity with other PM, the
@@ -59,34 +57,34 @@
 //			setbycreate) (mandatory) (2-bytes)
 //
 //		Inm Inpeq Histogram Table
-//			INM INPEQ histogram table: INMINPEQ1..17-L is a count of the near-end INMAINPEQi anomalies
-//			occurring on the line during the accumulation period. This parameter is subject to inhibiting -
-//			see clause 7.2.7.13 of [ITUT-G.997.1]. (R) (optional) (2-bytes * 17 entries-= 34-bytes)
+//			INMINPEQ1..17-L is a count of the near-end INMAINPEQi anomalies occurring on the line during the
+//			accumulation period. This parameter is subject to inhibiting - see clause 7.2.7.13 of
+//			[ITUT-G.997.1]. (R) (optional) (2-bytes * 17 entries-= 34-bytes)
 //
 //		Inm Total Measurement
-//			INM total measurement: INMME-L is a count of the near-end INMAME anomalies occurring on the line
-//			during the accumulation period. This parameter is subject to inhibiting - see clause 7.2.7.13 of
-//			[ITUT G.997.1]. (R) (optional) (2-bytes)
+//			INMME-L is a count of the near-end INMAME anomalies occurring on the line during the
+//			accumulation period. This parameter is subject to inhibiting - see clause 7.2.7.13 of [ITUT
+//			G.997.1]. (R) (optional) (2-bytes)
 //
 //		Inm Iat Histogram
-//			INM IAT histogram: INMIAT0..7-L is a count of the near-end INMAIATi anomalies occurring on the
-//			line during the accumulation period. This parameter is subject to inhibiting - see clause
-//			7.2.7.13 of [ITUT G.997.1]. (R) (optional) (2-bytes-* 8 entries-= 16-bytes)
+//			INMIAT0..7-L is a count of the near-end INMAIATi anomalies occurring on the line during the
+//			accumulation period. This parameter is subject to inhibiting - see clause 7.2.7.13 of [ITUT
+//			G.997.1]. (R) (optional) (2-bytes-* 8 entries-= 16-bytes)
 //
 //		Inm Inpeq Histogram Lfe Table
-//			INM INPEQ histogram LFE table: INMINPEQ1..17-LFE is a count of the far-end INMAINPEQi anomalies
-//			occurring on the line during the accumulation period. This parameter is subject to inhibiting -
-//			see clause 7.2.7.13 of [ITUT-G.997.1]. (R) (optional) (2-bytes * 17 entries-= 34-bytes)
+//			INMINPEQ1..17-LFE is a count of the far-end INMAINPEQi anomalies occurring on the line during
+//			the accumulation period. This parameter is subject to inhibiting - see clause 7.2.7.13 of
+//			[ITUT-G.997.1]. (R) (optional) (2-bytes * 17 entries-= 34-bytes)
 //
 //		Inm Total Measurement Lfe
-//			INM total measurement LFE: INMME-LFE is a count of the far-end INMAME anomalies occurring on the
-//			line during the accumulation period. This parameter is subject to inhibiting - see clause
-//			7.2.7.13 of [ITUT G.997.1]. (R) (optional) (2-bytes)
+//			INMME-LFE is a count of the far-end INMAME anomalies occurring on the line during the
+//			accumulation period. This parameter is subject to inhibiting - see clause 7.2.7.13 of [ITUT
+//			G.997.1]. (R) (optional) (2-bytes)
 //
 //		Inm Iat Histogram Lfe
-//			INM IAT histogram LFE: INMIAT0..7-LFE is a count of the far-end INMAIATi anomalies occurring on
-//			the line during the accumulation period. This parameter is subject to inhibiting - see clause
-//			7.2.7.13 of [ITUT G.997.1]. (R) (optional) (2-bytes-* 8 entries-= 16-bytes)
+//			INMIAT0..7-LFE is a count of the far-end INMAIATi anomalies occurring on the line during the
+//			accumulation period. This parameter is subject to inhibiting - see clause 7.2.7.13 of [ITUT
+//			G.997.1]. (R) (optional) (2-bytes-* 8 entries-= 16-bytes)
 //
 type XdslImpulseNoiseMonitorPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/xdsllineconfigurationprofilepart2.go b/generated/xdsllineconfigurationprofilepart2.go
index cf5f2a3..dfdd42c 100644
--- a/generated/xdsllineconfigurationprofilepart2.go
+++ b/generated/xdsllineconfigurationprofilepart2.go
@@ -27,11 +27,11 @@
 
 // XdslLineConfigurationProfilePart2ClassID is the 16-bit ID for the OMCI
 // Managed entity xDSL line configuration profile part 2
-const XdslLineConfigurationProfilePart2ClassID ClassID = ClassID(105)
+const XdslLineConfigurationProfilePart2ClassID = ClassID(105) // 0x0069
 
 var xdsllineconfigurationprofilepart2BME *ManagedEntityDefinition
 
-// XdslLineConfigurationProfilePart2 (class ID #105)
+// XdslLineConfigurationProfilePart2 (Class ID: #105 / 0x0069)
 //	The overall xDSL line configuration profile is modelled in several parts, all of which are
 //	associated together through a common ME ID (the client PPTP xDSL UNI part 1 has a single
 //	pointer, which refers to the entire set of line configuration profile parts).
@@ -41,48 +41,54 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. All xDSL and
-//			VDSL2 line configuration profiles and extensions that pertain to a given PPTP xDSL UNI must
-//			share a common ME ID. (R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. All xDSL and VDSL2 line
+//			configuration profiles and extensions that pertain to a given PPTP xDSL UNI must share a common
+//			ME ID. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Downstream Minimum Time Interval For Upshift Rate Adaptation
-//			Downstream minimum time interval for upshift rate adaptation: This parameter defines the
-//			interval during which the downstream noise margin must remain above the downstream upshift noise
-//			margin before the xTU-R attempts to increase the downstream net data rate. Its value ranges from
-//			0 to 16383-s. (R,-W, setbycreate) (optional) (2-bytes)
+//			This parameter defines the interval during which the downstream noise margin must remain above
+//			the downstream upshift noise margin before the xTU-R attempts to increase the downstream net
+//			data rate. Its value ranges from 0 to 16383-s. (R,-W, setbycreate) (optional) (2-bytes)
 //
 //		Upstream Minimum Time Interval For Upshift Rate Adaptation
-//			Upstream minimum time interval for upshift rate adaptation: This parameter defines the interval
-//			during which the upstream noise margin must remain above the upstream upshift noise margin
-//			before the xTU-C attempts to increase the upstream net data rate. Its value ranges from 0 to
-//			16383-s. (R,-W, setbycreate) (optional) (2-bytes)
+//			This parameter defines the interval during which the upstream noise margin must remain above the
+//			upstream upshift noise margin before the xTU-C attempts to increase the upstream net data rate.
+//			Its value ranges from 0 to 16383-s. (R,-W, setbycreate) (optional) (2-bytes)
 //
 //		Downstream Downshift Noise Margin
-//			Downstream downshift noise margin: If the downstream noise margin is below the downstream
-//			downshift noise margin and remains there for more than the downstream minimum time interval for
-//			downshift rate adaptation, the xTU-R attempts to decrease the downstream net data rate. This
-//			attribute's value ranges from 0 (0.0 dB) to 310 (31.0 dB). (R,-W, setbycreate) (optional)
-//			(2-bytes)
+//			If the downstream noise margin is below the downstream downshift noise margin and remains there
+//			for more than the downstream minimum time interval for downshift rate adaptation, the xTU-R
+//			attempts to decrease the downstream net data rate. This attribute's value ranges from 0 (0.0 dB)
+//			to 310 (31.0 dB). (R,-W, setbycreate) (optional) (2-bytes)
 //
 //		Upstream Downshift Noise Margin
-//			Upstream downshift noise margin: If the upstream noise margin is below the upstream downshift
-//			noise margin and remains there for more than the upstream minimum time interval for downshift
-//			rate adaptation, the xTUC attempts to decrease the upstream net data rate. This attribute's
-//			value ranges from 0 (0.0 dB) to 310 (31.0 dB). (R,-W, setbycreate) (optional) (2-bytes)
+//			If the upstream noise margin is below the upstream downshift noise margin and remains there for
+//			more than the upstream minimum time interval for downshift rate adaptation, the xTUC attempts to
+//			decrease the upstream net data rate. This attribute's value ranges from 0 (0.0 dB) to 310 (31.0
+//			dB). (R,-W, setbycreate) (optional) (2-bytes)
 //
 //		Downstream Minimum Time Interval For Downshift Rate Adaptation
-//			Downstream minimum time interval for downshift rate adaptation: This parameter defines the
-//			interval during which the downstream noise margin must remain below the downstream downshift
-//			noise margin before the xTU-R attempts to decrease the downstream net data rate. Its value
-//			ranges from 0 to 16383-s. (R,-W, setbycreate) (optional) (2-bytes)
+//			This parameter defines the interval during which the downstream noise margin must remain below
+//			the downstream downshift noise margin before the xTU-R attempts to decrease the downstream net
+//			data rate. Its value ranges from 0 to 16383-s. (R,-W, setbycreate) (optional) (2-bytes)
 //
 //		Upstream Minimum Time Interval For Downshift Rate Adaptation
-//			Upstream minimum time interval for downshift rate adaptation: This parameter defines the
-//			interval during which the upstream noise margin must remain below the upstream downshift noise
-//			margin before the xTU-C attempts to decrease the upstream net data rate. Its value ranges from 0
-//			to 16383-s. (R,-W, setbycreate) (optional) (2-bytes)
+//			This parameter defines the interval during which the upstream noise margin must remain below the
+//			upstream downshift noise margin before the xTU-C attempts to decrease the upstream net data
+//			rate. Its value ranges from 0 to 16383-s. (R,-W, setbycreate) (optional) (2-bytes)
 //
 //		Xtu Impedance State Forced
+//			This parameter forces the impedance state of the xTU-C. It applies only to the T/S interface,
+//			and is deprecated in the OMCI, which stands proxy for the Q interface. It is only valid for
+//			Annex A of [ITUT G.992.3], Annex A of [ITUT G.992.4] and Annex A of [ITUT G.992.5]. It is
+//			defined as follows.
+//
+//			1	Force the xTU-C to the disabled state.
+//
+//			2	Force the xTU-C to the inactive state.
+//
+//			3	Force the xTU-C to the active state.
+//
 //			(R,-W, setbycreate) (optional) (1-byte)
 //
 //		L0_Time
@@ -97,30 +103,30 @@
 //			W, setbycreate) (mandatory) (1 byte)
 //
 //		Downstream Maximum Nominal Power Spectral Density
-//			Downstream maximum nominal power spectral density: This attribute specifies the maximum nominal
-//			transmit PSD in the downstream direction during initialization and showtime. A single
-//			MAXNOMPSDds attribute is defined per mode enabled in the xTSE line configuration attribute. It
-//			is only valid for [ITUT-G.992.3], [ITUT-G.992.4] and [ITUT-G.992.5]. Its value ranges from 0
-//			(60.0-dBm/Hz) to 300 (-30-dBm/Hz). (R, W, setbycreate) (mandatory) (2 bytes)
+//			This attribute specifies the maximum nominal transmit PSD in the downstream direction during
+//			initialization and showtime. A single MAXNOMPSDds attribute is defined per mode enabled in the
+//			xTSE line configuration attribute. It is only valid for [ITUT-G.992.3], [ITUT-G.992.4] and
+//			[ITUT-G.992.5]. Its value ranges from 0 (60.0-dBm/Hz) to 300 (-30-dBm/Hz). (R, W, setbycreate)
+//			(mandatory) (2 bytes)
 //
 //		Upstream Maximum Nominal Power Spectral Density
-//			Upstream maximum nominal power spectral density: This attribute specifies the maximum nominal
-//			transmit PSD in the upstream direction during initialization and showtime. A single MAXNOMPSDus
-//			attribute is defined per mode enabled in the xTSE line configuration attribute. It is only valid
-//			for [ITUT-G.992.3], [ITUT-G.992.4] and [ITUT-G.993.2]. Its value ranges from 0 (-60.0-dBm/Hz) to
-//			300 (-30-dBm/Hz). (R, W, setbycreate) (mandatory) (2 bytes)
+//			This attribute specifies the maximum nominal transmit PSD in the upstream direction during
+//			initialization and showtime. A single MAXNOMPSDus attribute is defined per mode enabled in the
+//			xTSE line configuration attribute. It is only valid for [ITUT-G.992.3], [ITUT-G.992.4] and
+//			[ITUT-G.993.2]. Its value ranges from 0 (-60.0-dBm/Hz) to 300 (-30-dBm/Hz). (R, W, setbycreate)
+//			(mandatory) (2 bytes)
 //
 //		Downstream Maximum Nominal Aggregate Transmit Power
-//			Downstream maximum nominal aggregate transmit power: This attribute specifies the maximum
-//			nominal aggregate transmit power in the downstream direction during initialization and showtime.
-//			It is only valid for [ITUT-G.992.3], [ITUT-G.992.4], [ITUT-G.992.5] and [ITUT-G.993.2]. Its
-//			value ranges from 0 (0.0-dBm) to 255 (25.5-dBm). (R, W, setbycreate) (mandatory) (1-byte)
+//			This attribute specifies the maximum nominal aggregate transmit power in the downstream
+//			direction during initialization and showtime. It is only valid for [ITUT-G.992.3],
+//			[ITUT-G.992.4], [ITUT-G.992.5] and [ITUT-G.993.2]. Its value ranges from 0 (0.0-dBm) to 255
+//			(25.5-dBm). (R, W, setbycreate) (mandatory) (1-byte)
 //
 //		Upstream Maximum Nominal Aggregate Transmit Power
-//			Upstream maximum nominal aggregate transmit power: This parameter specifies the maximum nominal
-//			aggregate transmit power in the upstream direction during initialization and showtime. It is
-//			only valid for [ITUT-G.992.3], [ITUT-G.992.4] and [ITUT-G.992.5]. Its value ranges from 0
-//			(0.0-dBm) to 255 (25.5-dBm). (R, W, setbycreate) (mandatory) (1 byte)
+//			This parameter specifies the maximum nominal aggregate transmit power in the upstream direction
+//			during initialization and showtime. It is only valid for [ITUT-G.992.3], [ITUT-G.992.4] and
+//			[ITUT-G.992.5]. Its value ranges from 0 (0.0-dBm) to 255 (25.5-dBm). (R, W, setbycreate)
+//			(mandatory) (1 byte)
 //
 //		Upstream Maximum Aggregate_Receive Power
 //			Upstream maximum aggregate-receive power: This parameter specifies the maximum upstream
@@ -132,9 +138,9 @@
 //			power limit is to be applied. (R, W setbycreate) (mandatory) (2 bytes)
 //
 //		Vdsl2 Transmission System Enabling
-//			VDSL2 transmission system enabling: This configuration attribute extends the transmission system
-//			coding types to be allowed by the xTU-C. It is a bit map, defined as octet 8 (bits 57..64) in
-//			Table-9.7.12-1. (R, W, setbycreate) (optional) (1 byte)
+//			This configuration attribute extends the transmission system coding types to be allowed by the
+//			xTU-C. It is a bit map, defined as octet 8 (bits 57..64) in Table-9.7.12-1. (R, W, setbycreate)
+//			(optional) (1 byte)
 //
 type XdslLineConfigurationProfilePart2 struct {
 	ManagedEntityDefinition
@@ -167,7 +173,7 @@
 			11: Uint16Field("UpstreamMaximumNominalPowerSpectralDensity", UnsignedIntegerAttributeType, 0x0020, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 11),
 			12: ByteField("DownstreamMaximumNominalAggregateTransmitPower", UnsignedIntegerAttributeType, 0x0010, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 12),
 			13: ByteField("UpstreamMaximumNominalAggregateTransmitPower", UnsignedIntegerAttributeType, 0x0008, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 13),
-			14: Uint16Field("UpstreamMaximumAggregateReceivePower", UnsignedIntegerAttributeType, 0x0004, 0, mapset.NewSetWith(Read), false, false, false, 14),
+			14: Uint16Field("UpstreamMaximumAggregateReceivePower", UnsignedIntegerAttributeType, 0x0004, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 14),
 			15: ByteField("Vdsl2TransmissionSystemEnabling", UnsignedIntegerAttributeType, 0x0002, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, true, false, 15),
 		},
 		Access:  CreatedByOlt,
diff --git a/generated/xdsllineconfigurationprofilepart3.go b/generated/xdsllineconfigurationprofilepart3.go
index 2a80c19..48981e9 100644
--- a/generated/xdsllineconfigurationprofilepart3.go
+++ b/generated/xdsllineconfigurationprofilepart3.go
@@ -27,11 +27,11 @@
 
 // XdslLineConfigurationProfilePart3ClassID is the 16-bit ID for the OMCI
 // Managed entity xDSL line configuration profile part 3
-const XdslLineConfigurationProfilePart3ClassID ClassID = ClassID(106)
+const XdslLineConfigurationProfilePart3ClassID = ClassID(106) // 0x006a
 
 var xdsllineconfigurationprofilepart3BME *ManagedEntityDefinition
 
-// XdslLineConfigurationProfilePart3 (class ID #106)
+// XdslLineConfigurationProfilePart3 (Class ID: #106 / 0x006a)
 //	The overall xDSL line configuration profile is modelled in several parts, all of which are
 //	associated together through a common ME ID (the client PPTP xDSL UNI part 1 has a single
 //	pointer, which refers to the entire set of line configuration profile parts).
@@ -41,11 +41,20 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. All xDSL and
-//			VDSL2 line configuration profiles and extensions that pertain to a given PPTP xDSL UNI must
-//			share a common ME ID. (R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. All xDSL and VDSL2 line
+//			configuration profiles and extensions that pertain to a given PPTP xDSL UNI must share a common
+//			ME ID. (R, setbycreate) (mandatory) (2-bytes)
 //
 //		Loop Diagnostics Mode Forced Ldsf
+//			Loop diagnostics mode forced (LDSF): This configuration parameter forces the line into loop
+//			diagnostic mode via the xTU-C. It is only valid for [ITUT-G.992.3], [ITUT-G.992.4] and
+//			[ITUT-G.992.5]. It is defined as follows.
+//
+//			0	Inhibits the xTU-C from performing loop diagnostic mode procedures on the line. Loop
+//			diagnostic mode procedures may still be initiated by the xTU-R.
+//
+//			1	Forces the xTU-C to perform loop diagnostics procedures.
+//
 //			Only while the line power management state is L3 can the line be forced into loop diagnostic
 //			mode. When loop diagnostic procedures complete successfully, the ONU resets this attribute to 0.
 //			The line remains in the L3 idle state. The loop diagnostics data are available at least until
@@ -56,6 +65,12 @@
 //			timeout, then an initialization failure occurs. (R,-W, setbycreate) (mandatory) (1-byte)
 //
 //		Automode Cold Start Forced
+//			This attribute is defined to improve testing of the performance of xTUs supporting automode.
+//			Valid values are 0 and 1. A change in value of this attribute indicates a change in loop
+//			conditions applied to the devices under test. The xTUs reset any historical information used for
+//			automode, for shortening an ITU-T G.994.1 handshake, or for shortening the initialization
+//			procedure.
+//
 //			Automode is defined as the case where multiple operation modes are enabled in xTSE (Table
 //			9.7.12-1) and where the selection of the operation mode to be used for transmission depends, not
 //			only on the common capabilities of both xTUs (as exchanged in [ITU-T G.994.1]), but also on
@@ -76,19 +91,19 @@
 //			dB to 31 (31 dB). (R, W, setbycreate) (mandatory) (1 byte)
 //
 //		Force Inp Downstream
-//			Force INP downstream: When set to 1, the FORCEINPds attribute forces the framer settings of all
-//			downstream bearer channels to be selected such that the impulse noise protection (INP) computed
-//			according to the formula specified in the relevant Recommendation is greater than or equal to
-//			the minimal INP requirement. The default value 0 disables this function. (R, W) (mandatory for
-//			[ITU-T G.993.2], optional for other Recommendations that support it) (1 byte)
-//
-//		Force Inp Upstream
-//			Force INP upstream: When set to 1, the FORCEINPus attribute forces the framer settings of all
-//			upstream bearer channels to be selected such that the INP computed according to the formula
-//			specified in the relevant Recommendation is greater than or equal to the minimal INP
+//			When set to 1, the FORCEINPds attribute forces the framer settings of all downstream bearer
+//			channels to be selected such that the impulse noise protection (INP) computed according to the
+//			formula specified in the relevant Recommendation is greater than or equal to the minimal INP
 //			requirement. The default value 0 disables this function. (R, W) (mandatory for [ITU-T G.993.2],
 //			optional for other Recommendations that support it) (1 byte)
 //
+//		Force Inp Upstream
+//			When set to 1, the FORCEINPus attribute forces the framer settings of all upstream bearer
+//			channels to be selected such that the INP computed according to the formula specified in the
+//			relevant Recommendation is greater than or equal to the minimal INP requirement. The default
+//			value 0 disables this function. (R, W) (mandatory for [ITU-T G.993.2], optional for other
+//			Recommendations that support it) (1 byte)
+//
 //		Update Request Flag For Near_End Test Parameters
 //			Update request flag for near-end test parameters: The UPDATE-TEST-NE attribute forces an update
 //			of all near-end test parameters that can be updated during showtime in [ITU-T G.993.2]. Update
@@ -109,6 +124,11 @@
 //			when the flag is set via the OMCI or by an autonomous process in the system. (R,-W) (optional)
 //			(1-byte)
 //
+//			The following eight attributes configure the impulse noise monitoring (INM) function, whose
+//			results are available via the xDSL impulse noise monitor PM history data ME. The downstream
+//			attributes are applicable to [ITUT G.993.2], [ITUT G.992.3] and [ITUT G.992.5]. Only [ITUT
+//			G.993.2] supports the upstream attributes.
+//
 //		Inm Inter Arrival Time Offset Upstream
 //			INM inter-arrival time offset upstream: INMIATOus is the inter-arrival time (IAT) offset that
 //			the xTU-C receiver uses to determine in which bin of the IAT histogram the IAT is reported.
@@ -121,15 +141,14 @@
 //			from 0 to 7 in steps of 1. (R,-W) (optional) (1-byte)
 //
 //		Inm Cluster Continuation Value Upstream
-//			INM cluster continuation value upstream: INMCCus is the cluster continuation value that the
-//			xTU-C receiver uses in the cluster indication process described in the applicable
-//			Recommendation. Valid values for INMCC range from 0 to 64 DMT symbols in steps of 1 DMT symbol.
-//			(R,-W) (optional) (1-byte)
+//			INMCCus is the cluster continuation value that the xTU-C receiver uses in the cluster indication
+//			process described in the applicable Recommendation. Valid values for INMCC range from 0 to 64
+//			DMT symbols in steps of 1 DMT symbol. (R,-W) (optional) (1-byte)
 //
 //		Inm Equivalent Inp Mode Upstream
-//			INM equivalent INP mode upstream: INM_INPEQ_MODEus is the INM equivalent INP mode that the xTU-C
-//			receiver uses in the computation of the equivalent INP, as defined in the applicable
-//			Recommendation. Valid values for INM_INPEQ_MODE are 0..4. (R,-W) (optional) (1-byte)
+//			INM_INPEQ_MODEus is the INM equivalent INP mode that the xTU-C receiver uses in the computation
+//			of the equivalent INP, as defined in the applicable Recommendation. Valid values for
+//			INM_INPEQ_MODE are 0..4. (R,-W) (optional) (1-byte)
 //
 //		Inm Inter Arrival Time Offset Downstream
 //			INM inter-arrival time offset downstream: INMIATOds is the IAT offset that the xTU-R receiver
@@ -142,15 +161,14 @@
 //			range from 0 to 7 in steps of 1. (R,-W) (optional) (1-byte)
 //
 //		Inm Cluster Continuation Value Downstream
-//			INM cluster continuation value downstream: INMCCds is the cluster continuation value that the
-//			xTU-R receiver uses in the cluster indication process described in the applicable
-//			Recommendation. Valid values for INMCC range from 0 to 64 DMT symbols in steps of 1 DMT symbol.
-//			(R,-W) (optional) (1-byte)
+//			INMCCds is the cluster continuation value that the xTU-R receiver uses in the cluster indication
+//			process described in the applicable Recommendation. Valid values for INMCC range from 0 to 64
+//			DMT symbols in steps of 1 DMT symbol. (R,-W) (optional) (1-byte)
 //
 //		Inm Equivalent Inp Mode Downstream
-//			INM equivalent INP mode downstream: INM_INPEQ_MODEds is the INM equivalent INP mode that the
-//			xTU-R receiver uses in the computation of the equivalent INP, as defined in the applicable
-//			Recommendation. Valid values for INM_INPEQ_MODE are 0..4. (R,-W) (optional) (1-byte)
+//			INM_INPEQ_MODEds is the INM equivalent INP mode that the xTU-R receiver uses in the computation
+//			of the equivalent INP, as defined in the applicable Recommendation. Valid values for
+//			INM_INPEQ_MODE are 0..4. (R,-W) (optional) (1-byte)
 //
 type XdslLineConfigurationProfilePart3 struct {
 	ManagedEntityDefinition
diff --git a/generated/xdsllineinventoryandstatusdatapart1.go b/generated/xdsllineinventoryandstatusdatapart1.go
index 36eeea1..92dbed6 100644
--- a/generated/xdsllineinventoryandstatusdatapart1.go
+++ b/generated/xdsllineinventoryandstatusdatapart1.go
@@ -27,11 +27,11 @@
 
 // XdslLineInventoryAndStatusDataPart1ClassID is the 16-bit ID for the OMCI
 // Managed entity xDSL line inventory and status data part 1
-const XdslLineInventoryAndStatusDataPart1ClassID ClassID = ClassID(100)
+const XdslLineInventoryAndStatusDataPart1ClassID = ClassID(100) // 0x0064
 
 var xdsllineinventoryandstatusdatapart1BME *ManagedEntityDefinition
 
-// XdslLineInventoryAndStatusDataPart1 (class ID #100)
+// XdslLineInventoryAndStatusDataPart1 (Class ID: #100 / 0x0064)
 //	This ME contains part 1 of the line inventory and status data for an xDSL UNI. The ONU
 //	automatically creates or deletes an instance of this ME upon the creation or deletion of a PPTP
 //	xDSL UNI part 1.
@@ -41,9 +41,8 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP xDSL UNI part 1. (R)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP xDSL UNI part 1. (R) (mandatory) (2-bytes)
 //
 //		Xtu_C G.994.1 Vendor Id
 //			xTU-C G.994.1 vendor ID: This is the vendor ID as inserted by the xTU-C in the ITUT-G.994.1 CL
@@ -118,16 +117,51 @@
 //			combination with [ITU-T G.994.1] and the system vendor ID. (R) (mandatory) (4-bytes)
 //
 //		Xtu_C Transmission System Capability
+//			xTU-C transmission system capability: This attribute lists xTUC transmission system
+//			capabilities. It is a bit map, defined in Table 9.7.12-1. (R) (mandatory) (7-bytes)
+//
 //			NOTE 1 - This attribute is only 7-bytes long. An eighth byte identifying VDSL2 capabilities is
 //			defined in the VDSL2 line inventory and status data part 1 ME.
 //
 //		Xtu_R Transmission System Capability
+//			xTU-R transmission system capability: This attribute lists xTUR transmission system
+//			capabilities. It is a bit map, defined in Table 9.7.121. (R) (mandatory) (7-bytes)
+//
 //			NOTE 2 - This attribute is only 7-bytes long. An eighth byte identifying VDSL2 capabilities is
 //			defined in the VDSL2 line inventory and status data part 2 ME.
 //
 //		Initialization Success_Failure Cause
 //			(R) (mandatory) (1-byte)
 //
+//			Initialization success/failure cause: This parameter represents the success or failure cause of
+//			the last full initialization performed on the line. It is coded as follows.
+//
+//			0	Successful
+//
+//			1	Configuration error
+//
+//			This error occurs with inconsistencies in configuration parameters, e.g., when the line is
+//			initialized in an xDSL transmission system whose xTU does not support the configured maximum
+//			delay or the configured minimum or maximum data rate for one or more bearer channels.
+//
+//			2	Configuration not feasible on the line
+//
+//			This error occurs if the minimum data rate cannot be achieved on the line with the minimum noise
+//			margin, maximum PSD level, maximum delay and maximum bit error ratio for one or more bearer
+//			channels.
+//
+//			3	Communication problem
+//
+//			This error occurs, for example, due to corrupted messages, bad syntax messages, if no common
+//			mode can be selected in the ITUT-G.994.1 handshake procedure or due to a timeout.
+//
+//			4	No peer xTU detected
+//
+//			This error occurs if the peer xTU is not powered or not connected or if the line is too long to
+//			allow detection of a peer xTU.
+//
+//			5	Any other or unknown initialization failure cause.
+//
 type XdslLineInventoryAndStatusDataPart1 struct {
 	ManagedEntityDefinition
 	Attributes AttributeValueMap
diff --git a/generated/xdsllineinventoryandstatusdatapart2.go b/generated/xdsllineinventoryandstatusdatapart2.go
index 361203f..6385cfd 100644
--- a/generated/xdsllineinventoryandstatusdatapart2.go
+++ b/generated/xdsllineinventoryandstatusdatapart2.go
@@ -27,11 +27,11 @@
 
 // XdslLineInventoryAndStatusDataPart2ClassID is the 16-bit ID for the OMCI
 // Managed entity xDSL line inventory and status data part 2
-const XdslLineInventoryAndStatusDataPart2ClassID ClassID = ClassID(101)
+const XdslLineInventoryAndStatusDataPart2ClassID = ClassID(101) // 0x0065
 
 var xdsllineinventoryandstatusdatapart2BME *ManagedEntityDefinition
 
-// XdslLineInventoryAndStatusDataPart2 (class ID #101)
+// XdslLineInventoryAndStatusDataPart2 (Class ID: #101 / 0x0065)
 //	This ME contains part 2 of the line inventory and status data for an xDSL UNI. The ONU
 //	automatically creates or deletes an instance of this ME upon the creation or deletion of a PPTP
 //	xDSL UNI part 1.
@@ -44,18 +44,41 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP xDSL UNI part 1. (R)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP xDSL UNI part 1. (R) (mandatory) (2-bytes)
 //
 //		Xdsl Transmission System
+//			This parameter defines the transmission system in use. It is a bit map, defined in Table
+//			9.7.12-1. (R) (mandatory) (7-bytes)
+//
 //			NOTE 2 - This attribute is only 7-bytes long. An eighth byte identifying VDSL2 capabilities in
 //			use is defined in the VDSL2 line inventory and status data part 1 ME.
 //
 //		Line Power Management State
+//			The line has four possible power management states.
+//
+//			0	L0: Synchronized - This line state occurs when the line has full transmission (i.e.,
+//			showtime).
+//
+//			1	L1: Power down data transmission - This line state occurs when there is transmission on the
+//			line, but the net data rate is reduced (e.g., only for OAM and higher layer connection and
+//			session control). This state applies to [ITU-T G.992.2] only.
+//
+//			2	L2: Power down data transmission - This line state occurs when there is transmission on the
+//			line, but the net data rate is reduced (e.g., only for OAM and higher layer connection and
+//			session control). This state applies to [ITU-T G.992.3] and [ITUT-G.992.4] only.
+//
+//			3	L3: No power - This line state occurs when no power is transmitted on the line at all.
+//
 //			(R) (mandatory) (1-byte)
 //
 //		Downstream Line Attenuation
+//			The LATNds attribute is the squared magnitude of the channel characteristics function H(f)
+//			averaged over this band, and measured during loop diagnostic mode and initialization. The exact
+//			definition is included in the relevant xDSL Recommendation. The attribute value ranges from 0
+//			(0.0-dB) to 1270 (127.0-dB) dB. The special value 0xFFFF indicates that line attenuation is out
+//			of range. (R) (mandatory) (2-bytes)
+//
 //			NOTE 3 - [ITU-T G.993.2] specifies a per-band array to represent this attribute. The array is
 //			defined in the VDSL2 line inventory and status data part 3 ME. In an ITU-T G.993.2 context, the
 //			downstream line attenuation attribute should be set to 0 here, and populated in the VDSL2 line
@@ -67,54 +90,86 @@
 //			upstream line attenuation attribute should be set to 0 here, and populated in the VDSL2 line
 //			inventory and status data part 3 ME instead.
 //
+//			The LATNus attribute is the squared magnitude of the channel characteristics function H(f)
+//			averaged over this band, and measured during loop diagnostic mode and initialization. The exact
+//			definition is included in the relevant xDSL Recommendation. The attribute value ranges from 0
+//			(0.0-dB) to 1270 (127.0-dB). The special value 0xFFFF indicates that line attenuation is out of
+//			range. (R) (mandatory) (2-bytes)
+//
 //		Downstream Signal Attenuation
+//			The SATNds attribute is the measured difference in the total power transmitted in this band by
+//			the xTUC and the total power received in this band by the xTUR during loop diagnostic mode,
+//			initialization and showtime. The exact definition is included in the relevant xDSL
+//			Recommendation. The attribute value ranges from 0 (0.0-dB) to 1270 (127.0-dB). The special value
+//			0xFFFF indicates that signal attenuation is out of range. (R) (mandatory) (2-bytes)
+//
+//			NOTE 5 - During showtime, only a subset of the subcarriers may be transmitted by the xTU-C, as
+//			compared to loop diagnostic mode and initialization. Therefore, the downstream signal
+//			attenuation value during showtime may be significantly lower than the downstream signal
+//			attenuation value during loop diagnostic mode and initialization.
+//
 //			NOTE 6 - [ITU-T G.993.2] specifies a per-band array to represent this attribute. The array is
 //			defined in the VDSL2 line inventory and status data part 3 ME. In an ITU-T G.993.2 context, the
 //			downstream signal attenuation attribute should be set to 0 here, and populated in the VDSL2 line
 //			inventory and status data part 3 ME instead.
 //
 //		Upstream Signal Attenuation
+//			The SATNus attribute is the measured difference in decibels in the total power transmitted in
+//			this band by the xTUR and the total power received in this band by the xTUC during loop
+//			diagnostic mode, initialization and showtime. The exact definition is included in the relevant
+//			xDSL Recommendation. The attribute value ranges from 0 (0.0 dB) to 1270 (127.0-dB). The special
+//			value 0xFFFF indicates that signal attenuation is out of range. (R) (mandatory) (2-bytes)
+//
+//			NOTE 7 - During showtime, only a subset of the subcarriers may be transmitted by the xTU-R, as
+//			compared to loop diagnostic mode and initialization. Therefore, the upstream signal attenuation
+//			value during showtime may be significantly lower than the upstream signal attenuation value
+//			during loop diagnostic mode and initialization.
+//
 //			NOTE 8 - [ITU-T G.993.2] specifies a per-band array to represent this attribute. The array is
 //			defined in the VDSL2 line inventory and status data part 3 ME. In an ITU-T G.993.2 context, the
 //			upstream signal attenuation attribute should be set to 0 here, and populated in the VDSL2 line
 //			inventory and status data part 3 ME instead.
 //
 //		Downstream Snr Ratio Margin
-//			Downstream SNR ratio margin: The downstream SNR margin SNRMds is the maximum increase of noise
-//			power received at the xTUR, such that the BER requirements can still be met for all downstream
-//			bearer channels. The attribute value ranges from 0 (-64.0 dB) to 1270 (+63.0-dB). The special
-//			value 0xFFFF indicates that the attribute is out of range (R) (mandatory) (2-bytes)
+//			The downstream SNR margin SNRMds is the maximum increase of noise power received at the xTUR,
+//			such that the BER requirements can still be met for all downstream bearer channels. The
+//			attribute value ranges from 0 (-64.0 dB) to 1270 (+63.0-dB). The special value 0xFFFF indicates
+//			that the attribute is out of range (R) (mandatory) (2-bytes)
 //
 //		Upstream Snr Margin
-//			Upstream SNR margin: The upstream SNR margin SNRMus is the maximum increase of noise power
-//			received at the xTUC, such that the BER requirements can still be met for all upstream bearer
-//			channels. The attribute value ranges from 0 (-64.0 dB) to 1270 (+63.0 dB). The special value
-//			0xFFFF indicates that the attribute is out of range. (R) (mandatory) (2-bytes)
+//			The upstream SNR margin SNRMus is the maximum increase of noise power received at the xTUC, such
+//			that the BER requirements can still be met for all upstream bearer channels. The attribute value
+//			ranges from 0 (-64.0 dB) to 1270 (+63.0 dB). The special value 0xFFFF indicates that the
+//			attribute is out of range. (R) (mandatory) (2-bytes)
 //
 //		Downstream Maximum Attainable Data Rate
-//			Downstream maximum attainable data rate: The ATTNDRds attribute indicates the maximum downstream
-//			net data rate currently attainable. The rate is coded in bits per second. (R) (mandatory)
-//			(4-bytes)
+//			The ATTNDRds attribute indicates the maximum downstream net data rate currently attainable. The
+//			rate is coded in bits per second. (R) (mandatory) (4-bytes)
 //
 //		Upstream Maximum Attainable Data Rate
-//			Upstream maximum attainable data rate: The ATTNDRus attribute indicates the maximum upstream net
-//			data rate currently attainable. The rate is coded in bits per second. (R) (mandatory) (4-bytes)
+//			The ATTNDRus attribute indicates the maximum upstream net data rate currently attainable. The
+//			rate is coded in bits per second. (R) (mandatory) (4-bytes)
 //
 //		Downstream Actual Power Spectrum Density
-//			Downstream actual power spectrum density: The ACTPSDds attribute is the average downstream
-//			transmit power spectrum density over the subcarriers in use (subcarriers to which downstream
-//			user data are allocated) delivered by the xTUC at the UC reference point, at the instant of
-//			measurement. The attribute value ranges from 0 (-90.0-dBm/Hz) to 900 (0.0-dBm/Hz). The special
-//			value (0xFFFF) indicates that the parameter is out of range. (R) (mandatory) (2-bytes)
+//			The ACTPSDds attribute is the average downstream transmit power spectrum density over the
+//			subcarriers in use (subcarriers to which downstream user data are allocated) delivered by the
+//			xTUC at the UC reference point, at the instant of measurement. The attribute value ranges from 0
+//			(-90.0-dBm/Hz) to 900 (0.0-dBm/Hz). The special value (0xFFFF) indicates that the parameter is
+//			out of range. (R) (mandatory) (2-bytes)
 //
 //		Upstream Actual Power Spectrum Density
-//			Upstream actual power spectrum density: The ACTPSDus attribute is the average upstream transmit
-//			power spectrum density over the subcarriers in use (subcarriers to which upstream user data are
-//			allocated) delivered by the xTUR at the UR reference point, at the instant of measurement. The
-//			attribute value ranges from 0 (-90.0-dBm/Hz) to 900 (0.0-dBm/Hz). The special value 0xFFFF
-//			indicates that the attribute is out of range. (R) (mandatory) (2-bytes)
+//			The ACTPSDus attribute is the average upstream transmit power spectrum density over the
+//			subcarriers in use (subcarriers to which upstream user data are allocated) delivered by the xTUR
+//			at the UR reference point, at the instant of measurement. The attribute value ranges from 0
+//			(-90.0-dBm/Hz) to 900 (0.0-dBm/Hz). The special value 0xFFFF indicates that the attribute is out
+//			of range. (R) (mandatory) (2-bytes)
 //
 //		Downstream Actual Aggregate Transmit Power
+//			The ACTATPds attribute is the total amount of transmit power delivered by the xTUC at the UC
+//			reference point, at the instant of measurement. The attribute value ranges from 0 (-31.0-dBm) to
+//			620 (+31.0-dBm). The special value (0xFFFF) indicates that the parameter is out of range. (R)
+//			(mandatory) (2-bytes)
+//
 //			NOTE 9 - The downstream nominal aggregate transmit power may be taken as a best estimate of the
 //			parameter.
 //
@@ -122,10 +177,39 @@
 //			NOTE 10 - The upstream nominal aggregate transmit power may be taken as a best estimate of the
 //			parameter.
 //
+//			The ACTATPus attribute is the total amount of transmit power delivered by the xTUR at the UR
+//			reference point, at the instant of measurement. The attribute value ranges from 0 (-31.0-dBm) to
+//			620 (+31.0-dBm). The special value (0xFFFF) indicates that the parameter is out of range. (R)
+//			(mandatory) (2-bytes)
+//
 //		Initialization _ Last State Transmitted Downstream
+//			Initialization - last state transmitted downstream: This attribute represents the last
+//			successful transmitted initialization state in the downstream direction in the last full
+//			initialization performed on the line. Initialization states are defined in the individual xDSL
+//			Recommendations and are counted from 0 (if [ITUT-G.994.1] is used) or 1 (if [ITUT-G.994.1] is
+//			not used) up to showtime. This parameter must be interpreted along with the xDSL transmission
+//			system capabilities.
+//
+//			This parameter is available only when, after a failed full initialization, line diagnostic
+//			procedures are activated on the line. Line diagnostic procedures can be activated by the
+//			operator of the system (through the loop diagnostics mode forced attribute of the xDSL line
+//			configuration profile part 3) or autonomously by the xTU-C or xTU-R.
+//
 //			(R) (mandatory) (1-byte)
 //
 //		Initialization _ Last State Transmitted Upstream
+//			Initialization - last state transmitted upstream: This attribute represents the last successful
+//			transmitted initialization state in the upstream direction in the last full initialization
+//			performed on the line. Initialization states are defined in the individual xDSL Recommendations
+//			and are counted from 0 (if [ITUT-G.994.1] is used) or 1 (if [ITUT-G.994.1] is not used) up to
+//			showtime. This parameter must be interpreted along with the xDSL transmission system
+//			capabilities.
+//
+//			This parameter is available only when, after a failed full initialization, line diagnostic
+//			procedures are activated on the line. Line diagnostic procedures can be activated by the
+//			operator of the system (through the loop diagnostics mode forced attribute of the xDSL line
+//			configuration profile part 3) or autonomously by the xTU-C or xTU-R.
+//
 //			(R) (mandatory) (1-byte)
 //
 type XdslLineInventoryAndStatusDataPart2 struct {
diff --git a/generated/xdsllineinventoryandstatusdatapart5.go b/generated/xdsllineinventoryandstatusdatapart5.go
index c4f3aca..4e0cf45 100644
--- a/generated/xdsllineinventoryandstatusdatapart5.go
+++ b/generated/xdsllineinventoryandstatusdatapart5.go
@@ -27,11 +27,11 @@
 
 // XdslLineInventoryAndStatusDataPart5ClassID is the 16-bit ID for the OMCI
 // Managed entity xDSL line inventory and status data part 5
-const XdslLineInventoryAndStatusDataPart5ClassID ClassID = ClassID(325)
+const XdslLineInventoryAndStatusDataPart5ClassID = ClassID(325) // 0x0145
 
 var xdsllineinventoryandstatusdatapart5BME *ManagedEntityDefinition
 
-// XdslLineInventoryAndStatusDataPart5 (class ID #325)
+// XdslLineInventoryAndStatusDataPart5 (Class ID: #325 / 0x0145)
 //	This ME extends the attributes defined in the xDSL line inventory and status data parts 1..4.
 //	This ME reports FEXT and NEXT attributes, and pertains to Annex C of [ITUT G.992.3] (ADSL2) and
 //	Annex C of [ITUT G.992.5] (ADSL2plus).
@@ -43,107 +43,98 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP xDSL UNI part 1 ME. (R)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP xDSL UNI part 1 ME. (R) (mandatory) (2-bytes)
 //
 //		Fext Downstream Snr Margin
-//			FEXT downstream SNR margin: The FEXT SNRMds attribute is the downstream SNR margin measured
-//			during FEXTR duration at the ATU-R. The attribute value ranges from 0 (-64.0-dB) to 1270
-//			(+63.0-dB). The special value 0xFFFF indicates that the attribute is out of range. (R)
-//			(mandatory) (2-bytes)
+//			The FEXT SNRMds attribute is the downstream SNR margin measured during FEXTR duration at the
+//			ATU-R. The attribute value ranges from 0 (-64.0-dB) to 1270 (+63.0-dB). The special value 0xFFFF
+//			indicates that the attribute is out of range. (R) (mandatory) (2-bytes)
 //
 //		Next Downstream Snr Margin
-//			NEXT downstream SNR margin: The NEXT SNRMds attribute is the downstream SNR margin measured
-//			during NEXTR duration at the ATU-R. The attribute value ranges from 0 (-64.0-dB) to 1270
-//			(+63.0-dB). The special value 0xFFFF indicates that the attribute is out of range. (R)
-//			(mandatory) (2-bytes)
+//			The NEXT SNRMds attribute is the downstream SNR margin measured during NEXTR duration at the
+//			ATU-R. The attribute value ranges from 0 (-64.0-dB) to 1270 (+63.0-dB). The special value 0xFFFF
+//			indicates that the attribute is out of range. (R) (mandatory) (2-bytes)
 //
 //		Fext Upstream Snr Margin
-//			FEXT upstream SNR margin: The FEXT SNRMus attribute is the upstream SNR margin (see clause
-//			7.5.1.16 of [ITUT G.997.1]) measured during FEXTC duration at the ATU-C. The attribute value
-//			ranges from 0 (-64.0-dB) to 1270 (+63.0-dB). The special value 0xFFFF indicates that the
-//			attribute is out of range. (R) (mandatory) (2-bytes)
+//			The FEXT SNRMus attribute is the upstream SNR margin (see clause 7.5.1.16 of [ITUT G.997.1])
+//			measured during FEXTC duration at the ATU-C. The attribute value ranges from 0 (-64.0-dB) to
+//			1270 (+63.0-dB). The special value 0xFFFF indicates that the attribute is out of range. (R)
+//			(mandatory) (2-bytes)
 //
 //		Next Upstream Snr Margin
-//			NEXT upstream SNR margin: The NEXT SNRMus attribute is the upstream SNR margin (see clause
-//			7.5.1.16 of [ITUT-G.997.1]) measured during NEXTC duration at the ATU-C. The attribute value
-//			ranges from 0 (-64.0-dB) to 1270 (+63.0-dB). The special value 0xFFFF indicates that the
-//			attribute is out of range. (R) (mandatory) (2-bytes)
+//			The NEXT SNRMus attribute is the upstream SNR margin (see clause 7.5.1.16 of [ITUT-G.997.1])
+//			measured during NEXTC duration at the ATU-C. The attribute value ranges from 0 (-64.0-dB) to
+//			1270 (+63.0-dB). The special value 0xFFFF indicates that the attribute is out of range. (R)
+//			(mandatory) (2-bytes)
 //
 //		Fext Downstream Maximum Attainable Data Rate
-//			FEXT downstream maximum attainable data rate: The FEXT ATTNDRds attribute is the maximum
-//			downstream net data rate calculated from FEXT downstream SNR(f) (see clause 7.5.1.28.3.1 of
-//			[ITUT G.997.1]). The rate is coded in bits per second. (R) (mandatory) (4-bytes)
+//			The FEXT ATTNDRds attribute is the maximum downstream net data rate calculated from FEXT
+//			downstream SNR(f) (see clause 7.5.1.28.3.1 of [ITUT G.997.1]). The rate is coded in bits per
+//			second. (R) (mandatory) (4-bytes)
 //
 //		Next Downstream Maximum Attainable Data Rate
-//			NEXT downstream maximum attainable data rate: The NEXT ATTNDRds attribute is the maximum
-//			downstream net data rate calculated from NEXT downstream SNR(f) (see clause 7.5.1.28.3.2 of
-//			[ITUT G.997.1]). The rate is coded in bits per second. (R) (mandatory) (4-bytes)
+//			The NEXT ATTNDRds attribute is the maximum downstream net data rate calculated from NEXT
+//			downstream SNR(f) (see clause 7.5.1.28.3.2 of [ITUT G.997.1]). The rate is coded in bits per
+//			second. (R) (mandatory) (4-bytes)
 //
 //		Fext Upstream Maximum Attainable Data Rate
-//			FEXT upstream maximum attainable data rate: The FEXT ATTNDRus attribute is the maximum upstream
-//			net data rate calculated from FEXT upstream SNR(f) (see clause 7.5.1.28.6.1 of [ITUT G.997.1]).
-//			The rate is coded in bits per second. (R) (mandatory) (4-bytes)
+//			The FEXT ATTNDRus attribute is the maximum upstream net data rate calculated from FEXT upstream
+//			SNR(f) (see clause 7.5.1.28.6.1 of [ITUT G.997.1]). The rate is coded in bits per second. (R)
+//			(mandatory) (4-bytes)
 //
 //		Next Upstream Maximum Attainable Data Rate
-//			NEXT upstream maximum attainable data rate: The NEXT ATTNDRus attribute is the maximum upstream
-//			net data rate calculated from NEXT upstream SNR(f) (see clause 7.5.1.28.6.2 of [ITUT G.997.1]).
-//			The rate is coded in bits per second. (R) (mandatory) (4-bytes)
+//			The NEXT ATTNDRus attribute is the maximum upstream net data rate calculated from NEXT upstream
+//			SNR(f) (see clause 7.5.1.28.6.2 of [ITUT G.997.1]). The rate is coded in bits per second. (R)
+//			(mandatory) (4-bytes)
 //
 //		Fext Downstream Actual Power Spectral Density
-//			FEXT downstream actual power spectral density: The FEXT ACTPSDds attribute is the average
-//			downstream transmit PSD over the used subcarriers (see clause-7.5.1.21.1 of [ITUT G.997.1])
-//			calculated from the REFPSDds and RMSGIds for FEXTR duration. The attribute value ranges from 0
-//			(-90.0-dBm/Hz) to 900 (0.0-dBm/Hz). The special value 0xFFFF indicates that the parameter is out
-//			of range. (R) (mandatory) (2-bytes)
+//			The FEXT ACTPSDds attribute is the average downstream transmit PSD over the used subcarriers
+//			(see clause-7.5.1.21.1 of [ITUT G.997.1]) calculated from the REFPSDds and RMSGIds for FEXTR
+//			duration. The attribute value ranges from 0  (-90.0-dBm/Hz) to 900 (0.0-dBm/Hz). The special
+//			value 0xFFFF indicates that the parameter is out of range. (R) (mandatory) (2-bytes)
 //
 //		Next Downstream Actual Power Spectral Density
-//			NEXT downstream actual power spectral density: The NEXT ACTPSDds attribute is the average
-//			downstream transmit PSD over the used subcarriers (see clause-7.5.1.21.2 of [ITUT G.997.1])
-//			calculated from the REFPSDds and RMSGIds for NEXTR duration. The attribute value ranges from 0
-//			(-90.0-dBm/Hz) to 900 (0.0-dBm/Hz). The special value 0xFFFF indicates that the parameter is out
-//			of range. (R) (mandatory) (2-bytes)
+//			The NEXT ACTPSDds attribute is the average downstream transmit PSD over the used subcarriers
+//			(see clause-7.5.1.21.2 of [ITUT G.997.1]) calculated from the REFPSDds and RMSGIds for NEXTR
+//			duration. The attribute value ranges from 0  (-90.0-dBm/Hz) to 900 (0.0-dBm/Hz). The special
+//			value 0xFFFF indicates that the parameter is out of range. (R) (mandatory) (2-bytes)
 //
 //		Fext Upstream Actual Power Spectral Density
-//			FEXT upstream actual power spectral density: The FEXT ACTPSDus attribute is the average upstream
-//			transmit PSD over the used subcarriers (see clause-7.5.1.22.1 of [ITUT G.997.1]) calculated from
-//			the REFPSDus and RMSGIus for FEXTC duration. The attribute value ranges from 0 (-90.0-dBm/Hz) to
-//			900 (0.0-dBm/Hz). The special value 0xFFFF indicates that the parameter is out of range. (R)
-//			(mandatory) (2-bytes)
+//			The FEXT ACTPSDus attribute is the average upstream transmit PSD over the used subcarriers (see
+//			clause-7.5.1.22.1 of [ITUT G.997.1]) calculated from the REFPSDus and RMSGIus for FEXTC
+//			duration. The attribute value ranges from 0 (-90.0-dBm/Hz) to 900 (0.0-dBm/Hz). The special
+//			value 0xFFFF indicates that the parameter is out of range. (R) (mandatory) (2-bytes)
 //
 //		Next Upstream Actual Power Spectral Density
-//			NEXT upstream actual power spectral density: The NEXT ACTPSDus attribute is the average upstream
-//			transmit PSD over the used subcarriers (see clause-7.5.1.22.2 of [ITUT G.997.1]) calculated from
-//			the REFPSDus and RMSGIus for NEXTC duration. The attribute value ranges from 0 (-90.0-dBm/Hz) to
-//			900 (0.0-dBm/Hz). The special value 0xFFFF indicates that the parameter is out of range. (R)
-//			(mandatory) (2-bytes)
+//			The NEXT ACTPSDus attribute is the average upstream transmit PSD over the used subcarriers (see
+//			clause-7.5.1.22.2 of [ITUT G.997.1]) calculated from the REFPSDus and RMSGIus for NEXTC
+//			duration. The attribute value ranges from 0 (-90.0-dBm/Hz) to 900 (0.0-dBm/Hz). The special
+//			value 0xFFFF indicates that the parameter is out of range. (R) (mandatory) (2-bytes)
 //
 //		Fext Downstream Actual Aggregate Transmit Power
-//			FEXT downstream actual aggregate transmit power: The FEXT ACTATPds attribute is the total amount
-//			of transmit power (see clause 7.5.1.24.1 of [ITUT G.997.1]) calculated from PSDds measured
-//			during FEXTR duration at the ATU-R. The attribute value ranges from 0 (-31.0-dBm) to 620
-//			(+31.0-dBm). The special value 0xFFFF indicates that the parameter is out of range. (R)
-//			(mandatory) (2-bytes)
+//			The FEXT ACTATPds attribute is the total amount of transmit power (see clause 7.5.1.24.1 of
+//			[ITUT G.997.1]) calculated from PSDds measured during FEXTR duration at the ATU-R. The attribute
+//			value ranges from 0 (-31.0-dBm) to 620 (+31.0-dBm). The special value 0xFFFF indicates that the
+//			parameter is out of range. (R) (mandatory) (2-bytes)
 //
 //		Next Downstream Actual Aggregate Transmit Power
-//			NEXT downstream actual aggregate transmit power: The NEXT ACTATPds attribute is the total amount
-//			of transmit power (see clause 7.5.1.24.2 of [ITUT G.997.1]) calculated from PSDds measured
-//			during NEXTR duration at the ATU-R. The attribute value ranges from 0 (-31.0-dBm) to 620
-//			(+31.0-dBm). The special value 0xFFFF indicates that the parameter is out of range. (R)
-//			(mandatory) (2-bytes)
+//			The NEXT ACTATPds attribute is the total amount of transmit power (see clause 7.5.1.24.2 of
+//			[ITUT G.997.1]) calculated from PSDds measured during NEXTR duration at the ATU-R. The attribute
+//			value ranges from 0 (-31.0-dBm) to 620 (+31.0-dBm). The special value 0xFFFF indicates that the
+//			parameter is out of range. (R) (mandatory) (2-bytes)
 //
 //		Fext Upstream Actual Aggregate Transmit Power
-//			FEXT upstream actual aggregate transmit power: The FEXT ACTATPus attribute is the total transmit
-//			power (see clause 7.5.1.25.1 of [ITUT G.997.1]) calculated from PSDus measured during FEXTC
-//			duration at the ATU-C. The attribute value ranges from 0 (-31.0-dBm) to 620 (+31.0-dBm). The
-//			special value 0xFFFF indicates that the parameter is out of range. (R) (mandatory) (2-bytes)
+//			The FEXT ACTATPus attribute is the total transmit power (see clause 7.5.1.25.1 of [ITUT
+//			G.997.1]) calculated from PSDus measured during FEXTC duration at the ATU-C. The attribute value
+//			ranges from 0 (-31.0-dBm) to 620 (+31.0-dBm). The special value 0xFFFF indicates that the
+//			parameter is out of range. (R) (mandatory) (2-bytes)
 //
 //		Next Upstream Actual Aggregate Transmit Power
-//			NEXT upstream actual aggregate transmit power: The NEXT ACTATPus attribute is the total transmit
-//			power (see clause 7.5.1.25.2 of [ITUT G.997.1]) calculated from PSDus measured during NEXTC
-//			duration at the ATU-C. The attribute value ranges from 0 (-31.0-dBm) to 620 (+31.0-dBm). The
-//			special value 0xFFFF indicates that the parameter is out of range. (R) (mandatory) (2-bytes)
+//			The NEXT ACTATPus attribute is the total transmit power (see clause 7.5.1.25.2 of [ITUT
+//			G.997.1]) calculated from PSDus measured during NEXTC duration at the ATU-C. The attribute value
+//			ranges from 0 (-31.0-dBm) to 620 (+31.0-dBm). The special value 0xFFFF indicates that the
+//			parameter is out of range. (R) (mandatory) (2-bytes)
 //
 type XdslLineInventoryAndStatusDataPart5 struct {
 	ManagedEntityDefinition
diff --git a/generated/xdsllineinventoryandstatusdatapart8.go b/generated/xdsllineinventoryandstatusdatapart8.go
index 07e8dcc..ad1a629 100644
--- a/generated/xdsllineinventoryandstatusdatapart8.go
+++ b/generated/xdsllineinventoryandstatusdatapart8.go
@@ -27,11 +27,11 @@
 
 // XdslLineInventoryAndStatusDataPart8ClassID is the 16-bit ID for the OMCI
 // Managed entity xDSL line inventory and status data part 8
-const XdslLineInventoryAndStatusDataPart8ClassID ClassID = ClassID(414)
+const XdslLineInventoryAndStatusDataPart8ClassID = ClassID(414) // 0x019e
 
 var xdsllineinventoryandstatusdatapart8BME *ManagedEntityDefinition
 
-// XdslLineInventoryAndStatusDataPart8 (class ID #414)
+// XdslLineInventoryAndStatusDataPart8 (Class ID: #414 / 0x019e)
 //	This ME extends the attributes defined in the xDSL line inventory and status data parts-1..4.
 //
 //	Relationships
@@ -41,9 +41,8 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP xDSL UNI part 1 ME. (R)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP xDSL UNI part 1 ME. (R) (mandatory) (2-bytes)
 //
 //		Retransmission Used Downstream Rtx_Usedds
 //			Retransmission used downstream (RTX_USEDds): This parameter specifies whether [ITU-T G.998.4]
@@ -56,6 +55,10 @@
 //			range of values is given in clause 7.5.1.38 of [ITU-T G.997.1]. (R) (mandatory) (1 byte)
 //
 //		Date_Time_Stamping Of Near_End Test Parameters Stamp_Test_Ne
+//			Date/time-stamping of near-end test parameters (STAMP-TEST-NE): This parameter indicates the
+//			date/time when the near-end test parameters that can change during showtime were last updated.
+//			See clause 7.5.1.36.3 of [ITUT-G.997.1]. The format of this parameter is as follows.
+//
 //			(R) (optional) (7-bytes)
 //
 //		Date_Time_Stamping Of Far_End Test Parameters Stamp_Test_Fe
diff --git a/generated/xdslpsdmaskprofile.go b/generated/xdslpsdmaskprofile.go
index fe12ac1..9b455a3 100644
--- a/generated/xdslpsdmaskprofile.go
+++ b/generated/xdslpsdmaskprofile.go
@@ -27,11 +27,11 @@
 
 // XdslPsdMaskProfileClassID is the 16-bit ID for the OMCI
 // Managed entity xDSL PSD mask profile
-const XdslPsdMaskProfileClassID ClassID = ClassID(110)
+const XdslPsdMaskProfileClassID = ClassID(110) // 0x006e
 
 var xdslpsdmaskprofileBME *ManagedEntityDefinition
 
-// XdslPsdMaskProfile (class ID #110)
+// XdslPsdMaskProfile (Class ID: #110 / 0x006e)
 //	This ME contains a PSD mask profile for an xDSL UNI. An instance of this ME is created and
 //	deleted by the OLT.
 //
@@ -41,13 +41,59 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The value 0 is
-//			reserved. (R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. The value 0 is reserved. (R,
+//			setbycreate) (mandatory) (2-bytes)
 //
 //		Psd Mask Table
+//			This attribute is a table that defines the PSD mask applicable at the U-C2 reference point
+//			(downstream) or the U-R2 reference point (upstream). This mask may impose PSD restrictions in
+//			addition to the limit PSD mask defined in the relevant Recommendations ([ITUT G.992.3], [ITUT
+//			G.992.5], [ITUT-G.993.2]).
+//
+//			NOTE - In [ITUT G.997.1], this attribute is called PSDMASKds (downstream) and PSDMASKus
+//			(upstream). In [ITUT G.993.2], this attribute is called MIBMASKds (downstream) and MIBMASKus
+//			(upstream). The ITU-T G.993.2 MIBMASKus does not include breakpoints to shape US0.
+//
+//			The PSD mask is specified through a set of breakpoints. Each breakpoint comprises a 2-byte
+//			subcarrier index t, with a subcarrier spacing of 4.3125-kHz, and a 1-byte PSD mask level at that
+//			subcarrier. The set of breakpoints can then be represented as [(t1, PSD1), (t2, PSD2), ..., (tN,
+//			PSDN)]. The PSD mask level is coded as 0 (0.0-dBm/Hz) to 190  (-95.0-dBm/Hz), in steps of 0.5
+//			dB.
+//
+//			The maximum number of downstream breakpoints is 32. In the upstream direction, the maximum
+//			number of breakpoints is 4 for [ITU-T G.992.3] and 16 for [ITU-T G.993.2]. The requirements for
+//			a valid set of breakpoints are defined in the relevant Recommendations ([ITUT G.992.3],
+//			[ITUT-G.992.5], [ITUT G.993.2]).
+//
+//			Each table entry in this attribute comprises:
+//
+//			-	an entry number field (1-byte, first entry numbered 1);
+//
+//			-	a subcarrier index field, denoted t (2-bytes);
+//
+//			-	a PSD mask level field (1-byte).
+//
+//			By default, the PSD mask table is empty. Setting a subcarrier entry with a valid PSD mask level
+//			implies insertion into the table or replacement of an existing entry. Setting an entry's PSD
+//			mask level to 0xFF implies deletion from the table.
+//
 //			(R,-W) (mandatory) (4 * N bytes where N is the number of breakpoints)
 //
 //		Mask Valid
+//			This Boolean attribute controls and reports the status of the PSD mask attribute.
+//
+//			As a status report, the value false indicates that the PSD mask represented in this ME has not
+//			been impressed on the DSL equipment. The value true indicates that the PSD mask represented in
+//			this ME has been impressed on the DSL equipment.
+//
+//			This attribute behaves as follows.
+//
+//			o	If the OLT changes any of the PSD mask table entries or sets mask valid false, then mask valid
+//			is false.
+//
+//			o	If mask valid is false and the OLT sets mask valid true, the ONU impresses the PSD mask data
+//			on the DSL equipment.
+//
 //			(R,-W) (mandatory) (1-byte)
 //
 type XdslPsdMaskProfile struct {
diff --git a/generated/xdslsubcarriermaskingdownstreamprofile.go b/generated/xdslsubcarriermaskingdownstreamprofile.go
index 9e6ed17..05e7d55 100644
--- a/generated/xdslsubcarriermaskingdownstreamprofile.go
+++ b/generated/xdslsubcarriermaskingdownstreamprofile.go
@@ -27,11 +27,11 @@
 
 // XdslSubcarrierMaskingDownstreamProfileClassID is the 16-bit ID for the OMCI
 // Managed entity xDSL subcarrier masking downstream profile
-const XdslSubcarrierMaskingDownstreamProfileClassID ClassID = ClassID(108)
+const XdslSubcarrierMaskingDownstreamProfileClassID = ClassID(108) // 0x006c
 
 var xdslsubcarriermaskingdownstreamprofileBME *ManagedEntityDefinition
 
-// XdslSubcarrierMaskingDownstreamProfile (class ID #108)
+// XdslSubcarrierMaskingDownstreamProfile (Class ID: #108 / 0x006c)
 //	This ME contains the subcarrier masking downstream profile for an xDSL UNI. Instances of this ME
 //	are created and deleted by the OLT.
 //
@@ -41,25 +41,49 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The value 0 is
-//			reserved. (R, set-by-create) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. The value 0 is reserved. (R, set-
+//			by-create) (mandatory) (2-bytes)
+//
+//			The four following attributes are bit maps that represent downstream mask values for subcarriers
+//			1..128 (mask 1) through 385..512 (mask 4). The MSB of the first byte corresponds to the lowest
+//			numbered subcarrier, and the LSB of the last byte corresponds to the highest. Each bit position
+//			defines whether the corresponding downstream subcarrier is masked (1) or not masked (0).
+//
+//			The number of xDSL subcarriers, downstream (NSCds) is the highest numbered subcarrier that can
+//			be transmitted in the downstream direction. For [ITUT-G.992.3], [ITUT-G.992.4] and
+//			[ITUT-G.992.5], it is defined in the corresponding Recommendation. For [ITUT-G.992.1], NSCds =
+//			256 and for [ITUT-G.992.2], NSCds-= 128.
 //
 //		Downstream Subcarrier Mask 1
-//			Downstream subcarrier mask 1: Subcarriers 1 to 128. (R,-W, set-by-create) (mandatory) (16-bytes)
+//			Subcarriers 1 to 128. (R,-W, set-by-create) (mandatory) (16-bytes)
 //
 //		Downstream Subcarrier Mask 2
-//			Downstream subcarrier mask 2: Subcarriers 129 to 256. (R,-W) (mandatory for modems that support
-//			NSCds-> 128) (16-bytes)
+//			Subcarriers 129 to 256. (R,-W) (mandatory for modems that support NSCds-> 128) (16-bytes)
 //
 //		Downstream Subcarrier Mask 3
-//			Downstream subcarrier mask 3: Subcarriers 257 to 384. (R,-W) (mandatory for modems that support
-//			NSCds-> 256) (16-bytes)
+//			Subcarriers 257 to 384. (R,-W) (mandatory for modems that support NSCds-> 256) (16-bytes)
 //
 //		Downstream Subcarrier Mask 4
-//			Downstream subcarrier mask 4: Subcarriers 385 to 512. (R,-W) (mandatory for modems that support
-//			NSCds-> 384) (16-bytes)
+//			Subcarriers 385 to 512. (R,-W) (mandatory for modems that support NSCds-> 384) (16-bytes)
 //
 //		Mask Valid
+//			This Boolean attribute controls and reports the operational status of the downstream subcarrier
+//			mask attributes.
+//
+//			If this attribute is true (1), the downstream subcarrier mask represented in this ME has been
+//			impressed on the DSL equipment.
+//
+//			If this attribute is false (0), the downstream subcarrier mask represented in this ME has not
+//			been impressed on the DSL equipment. The default value is false.
+//
+//			The value of this attribute can be modified by the ONU and OLT, as follows.
+//
+//			o	If the OLT changes any of the four mask attributes or sets mask valid false, then mask valid
+//			is false.
+//
+//			o	If mask valid is false and the OLT sets mask valid true, the ONU impresses the downstream
+//			subcarrier mask data on to the DSL equipment.
+//
 //			(R,-W) (mandatory) (1-byte)
 //
 type XdslSubcarrierMaskingDownstreamProfile struct {
diff --git a/generated/xdslsubcarriermaskingupstreamprofile.go b/generated/xdslsubcarriermaskingupstreamprofile.go
index dc7d3bc..0e02784 100644
--- a/generated/xdslsubcarriermaskingupstreamprofile.go
+++ b/generated/xdslsubcarriermaskingupstreamprofile.go
@@ -27,11 +27,11 @@
 
 // XdslSubcarrierMaskingUpstreamProfileClassID is the 16-bit ID for the OMCI
 // Managed entity xDSL subcarrier masking upstream profile
-const XdslSubcarrierMaskingUpstreamProfileClassID ClassID = ClassID(109)
+const XdslSubcarrierMaskingUpstreamProfileClassID = ClassID(109) // 0x006d
 
 var xdslsubcarriermaskingupstreamprofileBME *ManagedEntityDefinition
 
-// XdslSubcarrierMaskingUpstreamProfile (class ID #109)
+// XdslSubcarrierMaskingUpstreamProfile (Class ID: #109 / 0x006d)
 //	This ME contains the subcarrier masking upstream profile for an xDSL UNI. An instance of this ME
 //	is created and deleted by the OLT.
 //
@@ -41,10 +41,15 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The value 0 is
-//			reserved. (R, setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. The value 0 is reserved. (R,
+//			setbycreate) (mandatory) (2-bytes)
 //
 //		Upstream Subcarrier Mask
+//			This attribute is a bit map representing upstream mask values for subcarriers 1 to 64. The MSB
+//			of byte 1 corresponds to subcarrier 1, and the LSB of byte 8 corresponds to subcarrier 64. Each
+//			bit position defines whether the corresponding downstream subcarrier is masked (1) or not masked
+//			(0).
+//
 //			Subcarrier number 1 is the lowest, and the number of xDSL subcarriers, upstream (NSCus) is the
 //			highest subcarrier that can be transmitted in the upstream direction. For [ITUT-G.992.3],
 //			[ITUT-G.992.4] and [ITUT-G.992.5], it is defined in the corresponding Recommendation. For Annex
diff --git a/generated/xdslxtu-cchannelperformancemonitoringhistorydata.go b/generated/xdslxtu-cchannelperformancemonitoringhistorydata.go
index 560a5af..00e0827 100644
--- a/generated/xdslxtu-cchannelperformancemonitoringhistorydata.go
+++ b/generated/xdslxtu-cchannelperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // XdslXtuCChannelPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity xDSL xTU-C channel performance monitoring history data
-const XdslXtuCChannelPerformanceMonitoringHistoryDataClassID ClassID = ClassID(114)
+const XdslXtuCChannelPerformanceMonitoringHistoryDataClassID = ClassID(114) // 0x0072
 
 var xdslxtucchannelperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// XdslXtuCChannelPerformanceMonitoringHistoryData (class ID #114)
+// XdslXtuCChannelPerformanceMonitoringHistoryData (Class ID: #114 / 0x0072)
 //	This ME collects PM data of an xTUC to xTUR channel as seen from the xTU-C. Instances of this ME
 //	are created and deleted by the OLT.
 //
@@ -43,14 +43,13 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The two MSBs of
-//			the first byte are the bearer channel ID. Excluding the first 2-bits of the first byte, the
-//			remaining part of the ME ID is identical to that of this ME's parent PPTP xDSL UNI part 1. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. The two MSBs of the first byte are
+//			the bearer channel ID. Excluding the first 2-bits of the first byte, the remaining part of the
+//			ME ID is identical to that of this ME's parent PPTP xDSL UNI part 1. (R, setbycreate)
+//			(mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -58,28 +57,24 @@
 //			data 2 ME is optional. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Corrected Blocks
-//			Corrected blocks: This attribute counts blocks received with errors that were corrected on this
-//			channel. (R) (mandatory) (4-bytes)
-//
-//		Uncorrected Blocks
-//			Uncorrected blocks: This attribute counts blocks received with uncorrectable errors on this
-//			channel. (R) (mandatory) (4-bytes)
-//
-//		Transmitted Blocks
-//			Transmitted blocks:	This attribute counts encoded blocks transmitted on this channel. (R)
+//			This attribute counts blocks received with errors that were corrected on this channel. (R)
 //			(mandatory) (4-bytes)
 //
-//		Received Blocks
-//			Received blocks: This attribute counts encoded blocks received on this channel. (R) (mandatory)
+//		Uncorrected Blocks
+//			This attribute counts blocks received with uncorrectable errors on this channel. (R) (mandatory)
 //			(4-bytes)
 //
+//		Transmitted Blocks
+//			This attribute counts encoded blocks transmitted on this channel. (R) (mandatory) (4-bytes)
+//
+//		Received Blocks
+//			This attribute counts encoded blocks received on this channel. (R) (mandatory) (4-bytes)
+//
 //		Code Violations
-//			Code violations: This attribute counts CRC-8 anomalies in the bearer channel. (R) (mandatory)
-//			(2-bytes)
+//			This attribute counts CRC-8 anomalies in the bearer channel. (R) (mandatory) (2-bytes)
 //
 //		Forward Error Corrections
-//			Forward error corrections: This attribute counts FEC anomalies in the bearer channel. (R)
-//			(mandatory) (2-bytes)
+//			This attribute counts FEC anomalies in the bearer channel. (R) (mandatory) (2-bytes)
 //
 type XdslXtuCChannelPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/xdslxtu-cperformancemonitoringhistorydata.go b/generated/xdslxtu-cperformancemonitoringhistorydata.go
index feecdac..caa6f42 100644
--- a/generated/xdslxtu-cperformancemonitoringhistorydata.go
+++ b/generated/xdslxtu-cperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // XdslXtuCPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity xDSL xTU-C performance monitoring history data
-const XdslXtuCPerformanceMonitoringHistoryDataClassID ClassID = ClassID(112)
+const XdslXtuCPerformanceMonitoringHistoryDataClassID = ClassID(112) // 0x0070
 
 var xdslxtucperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// XdslXtuCPerformanceMonitoringHistoryData (class ID #112)
+// XdslXtuCPerformanceMonitoringHistoryData (Class ID: #112 / 0x0070)
 //	This ME collects PM data on the xTUC to xTUR path as seen from the xTU-C. Instances of this ME
 //	are created and deleted by the OLT.
 //
@@ -42,29 +42,28 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP xDSL UNI part 1. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP xDSL UNI part 1. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 and 2 MEs
 //			that contain PM threshold values. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Loss Of Frame Seconds
-//			Loss of frame seconds: (R) (mandatory) (2-bytes)
+//			(R) (mandatory) (2-bytes)
 //
 //		Loss Of Signal Seconds
-//			Loss of signal seconds: (R) (mandatory) (2-bytes)
+//			(R) (mandatory) (2-bytes)
 //
 //		Loss Of Link Seconds
-//			Loss of link seconds: (R) (mandatory) (2-bytes)
+//			(R) (mandatory) (2-bytes)
 //
 //		Loss Of Power Seconds
-//			Loss of power seconds: (R) (mandatory) (2-bytes)
+//			(R) (mandatory) (2-bytes)
 //
 //		Errored Seconds Es
 //			Errored seconds (ES): This attribute counts 1-s intervals with one or more CRC8 anomalies summed
@@ -72,48 +71,65 @@
 //			SEF defects, or one or more LPR defects. (R) (mandatory) (2-bytes)
 //
 //		Severely Errored Seconds
+//			This attribute counts severely errored seconds (SES-L). An SES is declared if, during a 1-s
+//			interval, there were 18 or more CRC8 anomalies in one or more of the received bearer channels,
+//			or one or more LOS defects, or one or more SEF defects, or one or more LPR defects.
+//
+//			If the relevant Recommendation ([ITUT G.992.3], [ITUT G.992.5] or [ITUT G.993.2]) supports a 1-s
+//			normalized CRC-8 anomaly counter increment, the 1-s SES counter follows this value instead of
+//			counting CRC-8 anomalies directly.
+//
+//			If a common CRC is applied over multiple bearer channels, then each related CRC-8 anomaly is
+//			counted only once for the whole set of bearer channels over which the CRC is applied.
+//
 //			(R) (mandatory) (2-bytes)
 //
 //		Line Initializations
-//			Line initializations: This attribute counts the total number of full initializations attempted
-//			on the line, both successful and failed. (R) (mandatory) (2-bytes)
+//			This attribute counts the total number of full initializations attempted on the line, both
+//			successful and failed. (R) (mandatory) (2-bytes)
 //
 //		Failed Line Initializations
-//			Failed line initializations: This attribute counts the total number of failed full
-//			initializations during the accumulation period. A failed full initialization occurs when
-//			showtime is not reached at the end of the full initialization procedure. (R) (mandatory)
-//			(2-bytes)
+//			This attribute counts the total number of failed full initializations during the accumulation
+//			period. A failed full initialization occurs when showtime is not reached at the end of the full
+//			initialization procedure. (R) (mandatory) (2-bytes)
 //
 //		Short Initializations
-//			Short initializations: This attribute counts the total number of fast retrains or short
-//			initializations attempted on the line, successful and failed. Fast retrain is defined in [ITUT
-//			G.992.2]. Short initialization is defined in [ITUT-G.992.3] and [ITUT G.992.4]. (R) (optional)
-//			(2-bytes)
+//			This attribute counts the total number of fast retrains or short initializations attempted on
+//			the line, successful and failed. Fast retrain is defined in [ITUT G.992.2]. Short initialization
+//			is defined in [ITUT-G.992.3] and [ITUT G.992.4]. (R) (optional) (2-bytes)
 //
 //		Failed Short Initializations
+//			This attribute counts the total number of failed fast retrains or short initializations during
+//			the accumulation period, e.g., when:
+//
+//			-	a CRC error is detected;
+//
+//			-	a timeout occurs;
+//
+//			-	a fast retrain profile is unknown.
+//
 //			(R) (optional) (2-bytes)
 //
 //		Fec Seconds
-//			FEC seconds: This attribute counts seconds during which there was an FEC anomaly. (R)
-//			(mandatory) (2-bytes)
+//			This attribute counts seconds during which there was an FEC anomaly. (R) (mandatory) (2-bytes)
 //
 //		Unavailable Seconds
-//			Unavailable seconds: This attribute counts 1-s intervals during which the xDSL UNI is
-//			unavailable. The line becomes unavailable at the onset of 10 contiguous SES-Ls. The 10 SES-Ls
-//			are included in unavailable time. Once unavailable, the line becomes available at the onset of
-//			10-contiguous seconds that are not severely errored. The 10-s with no SESLs are excluded from
-//			unavailable time. Some attribute counts are inhibited during unavailability - see clause
-//			7.2.7.13 of [ITUT G.997.1]. (R) (mandatory) (2-bytes)
+//			This attribute counts 1-s intervals during which the xDSL UNI is unavailable. The line becomes
+//			unavailable at the onset of 10 contiguous SES-Ls. The 10 SES-Ls are included in unavailable
+//			time. Once unavailable, the line becomes available at the onset of 10-contiguous seconds that
+//			are not severely errored. The 10-s with no SESLs are excluded from unavailable time. Some
+//			attribute counts are inhibited during unavailability - see clause 7.2.7.13 of [ITUT G.997.1].
+//			(R) (mandatory) (2-bytes)
 //
 //		Sos Success Count, Near End
-//			SOS success count, near end: The SOS-SUCCESS-NE attribute is a count of the total number of
-//			successful SOS procedures initiated by the near-end xTU on the line during the accumulation
-//			period. Successful SOS is defined in clause-12.1.4 of [ITUT G.993.2]. (R) (optional) (2-bytes)
+//			The SOS-SUCCESS-NE attribute is a count of the total number of successful SOS procedures
+//			initiated by the near-end xTU on the line during the accumulation period. Successful SOS is
+//			defined in clause-12.1.4 of [ITUT G.993.2]. (R) (optional) (2-bytes)
 //
 //		Sos Success Count, Far End
-//			SOS success count, far end: The SOS-SUCCESS-FE attribute is a count of the total number of
-//			successful SOS procedures initiated by the far-end xTU on the line during the accumulation
-//			period. Successful SOS is defined in clause 12.1.4 of [ITUT-G.993.2]. (R) (optional) (2-bytes)
+//			The SOS-SUCCESS-FE attribute is a count of the total number of successful SOS procedures
+//			initiated by the far-end xTU on the line during the accumulation period. Successful SOS is
+//			defined in clause 12.1.4 of [ITUT-G.993.2]. (R) (optional) (2-bytes)
 //
 type XdslXtuCPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/xdslxtu-cperformancemonitoringhistorydatapart2.go b/generated/xdslxtu-cperformancemonitoringhistorydatapart2.go
index 162326a..bc65164 100644
--- a/generated/xdslxtu-cperformancemonitoringhistorydatapart2.go
+++ b/generated/xdslxtu-cperformancemonitoringhistorydatapart2.go
@@ -27,11 +27,11 @@
 
 // XdslXtuCPerformanceMonitoringHistoryDataPart2ClassID is the 16-bit ID for the OMCI
 // Managed entity xDSL xTU-C performance monitoring history data part 2
-const XdslXtuCPerformanceMonitoringHistoryDataPart2ClassID ClassID = ClassID(408)
+const XdslXtuCPerformanceMonitoringHistoryDataPart2ClassID = ClassID(408) // 0x0198
 
 var xdslxtucperformancemonitoringhistorydatapart2BME *ManagedEntityDefinition
 
-// XdslXtuCPerformanceMonitoringHistoryDataPart2 (class ID #408)
+// XdslXtuCPerformanceMonitoringHistoryDataPart2 (Class ID: #408 / 0x0198)
 //	This ME collects PM data on the xTUC to xTUR path as seen from the xTU-C. Instances of this ME
 //	are created and deleted by the OLT.
 //
@@ -42,13 +42,12 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP xDSL UNI part 1. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP xDSL UNI part 1. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 and 2 MEs
diff --git a/generated/xdslxtu-rchannelperformancemonitoringhistorydata.go b/generated/xdslxtu-rchannelperformancemonitoringhistorydata.go
index ca81538..d9602df 100644
--- a/generated/xdslxtu-rchannelperformancemonitoringhistorydata.go
+++ b/generated/xdslxtu-rchannelperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // XdslXtuRChannelPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity xDSL xTU-R channel performance monitoring history data
-const XdslXtuRChannelPerformanceMonitoringHistoryDataClassID ClassID = ClassID(115)
+const XdslXtuRChannelPerformanceMonitoringHistoryDataClassID = ClassID(115) // 0x0073
 
 var xdslxturchannelperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// XdslXtuRChannelPerformanceMonitoringHistoryData (class ID #115)
+// XdslXtuRChannelPerformanceMonitoringHistoryData (Class ID: #115 / 0x0073)
 //	This ME collects PM data of the xTUC to xTUR channel as seen from the xTU-R. Instances of this
 //	ME are created and deleted by the OLT.
 //
@@ -43,14 +43,13 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. The two MSBs of
-//			the first byte are the bearer channel ID. Excluding the first 2-bits of the first byte, the
-//			remaining part of the ME ID is identical to that of this ME's parent PPTP xDSL UNI part 1. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. The two MSBs of the first byte are
+//			the bearer channel ID. Excluding the first 2-bits of the first byte, the remaining part of the
+//			ME ID is identical to that of this ME's parent PPTP xDSL UNI part 1. (R, setbycreate)
+//			(mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -58,31 +57,28 @@
 //			data 2 ME is optional. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Corrected Blocks
-//			Corrected blocks: This attribute counts blocks received with errors that were corrected on this
-//			channel. (R) (mandatory) (4-bytes)
-//
-//		Uncorrected Blocks
-//			Uncorrected blocks: This attribute counts blocks received with uncorrectable errors on this
-//			channel. (R) (mandatory) (4-bytes)
-//
-//		Transmitted Blocks
-//			Transmitted blocks: This attribute counts encoded blocks transmitted on this channel. (R)
+//			This attribute counts blocks received with errors that were corrected on this channel. (R)
 //			(mandatory) (4-bytes)
 //
-//		Received Blocks
-//			Received blocks: This attribute counts encoded blocks received on this channel. (R) (mandatory)
+//		Uncorrected Blocks
+//			This attribute counts blocks received with uncorrectable errors on this channel. (R) (mandatory)
 //			(4-bytes)
 //
+//		Transmitted Blocks
+//			This attribute counts encoded blocks transmitted on this channel. (R) (mandatory) (4-bytes)
+//
+//		Received Blocks
+//			This attribute counts encoded blocks received on this channel. (R) (mandatory) (4-bytes)
+//
 //		Code Violations
-//			Code violations: This attribute counts FEBE anomalies reported in the downstream bearer channel.
-//			If the CRC is applied over multiple bearer channels, then each related FEBE anomaly increments
-//			each of the counters related to the individual bearer channels. (R) (mandatory) (2-bytes)
+//			This attribute counts FEBE anomalies reported in the downstream bearer channel. If the CRC is
+//			applied over multiple bearer channels, then each related FEBE anomaly increments each of the
+//			counters related to the individual bearer channels. (R) (mandatory) (2-bytes)
 //
 //		Forward Error Corrections
-//			Forward error corrections: This attribute counts FFEC anomalies reported in the downstream
-//			bearer channel. If FEC is applied over multiple bearer channels, each related FFEC anomaly
-//			increments each of the counters related to the individual bearer channels. (R) (mandatory)
-//			(2-bytes)
+//			This attribute counts FFEC anomalies reported in the downstream bearer channel. If FEC is
+//			applied over multiple bearer channels, each related FFEC anomaly increments each of the counters
+//			related to the individual bearer channels. (R) (mandatory) (2-bytes)
 //
 type XdslXtuRChannelPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/xdslxtu-rperformancemonitoringhistorydata.go b/generated/xdslxtu-rperformancemonitoringhistorydata.go
index d2eb1a3..a649da5 100644
--- a/generated/xdslxtu-rperformancemonitoringhistorydata.go
+++ b/generated/xdslxtu-rperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // XdslXtuRPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity xDSL xTU-R performance monitoring history data
-const XdslXtuRPerformanceMonitoringHistoryDataClassID ClassID = ClassID(113)
+const XdslXtuRPerformanceMonitoringHistoryDataClassID = ClassID(113) // 0x0071
 
 var xdslxturperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// XdslXtuRPerformanceMonitoringHistoryData (class ID #113)
+// XdslXtuRPerformanceMonitoringHistoryData (Class ID: #113 / 0x0071)
 //	This ME collects PM data of the xTUC to xTUR path as seen from the xTU-R. Instances of this ME
 //	are created and deleted by the OLT.
 //
@@ -42,13 +42,12 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP xDSL UNI part 1. (R,
-//			setbycreate) (mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP xDSL UNI part 1. (R, setbycreate) (mandatory)
+//			(2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -56,29 +55,48 @@
 //			data 2 ME is optional. (R,-W, setbycreate) (mandatory) (2-bytes)
 //
 //		Loss Of Frame Seconds
-//			Loss of frame seconds: (R) (mandatory) (2-bytes)
+//			(R) (mandatory) (2-bytes)
 //
 //		Loss Of Signal Seconds
-//			Loss of signal seconds: (R) (mandatory) (2-bytes)
+//			(R) (mandatory) (2-bytes)
 //
 //		Loss Of Power Seconds
-//			Loss of power seconds: (R) (mandatory) (2-bytes)
+//			(R) (mandatory) (2-bytes)
 //
 //		Errored Seconds
-//			Errored seconds: This attribute counts 1-s intervals with one or more far end block error (FEBE)
-//			anomalies summed over all transmitted bearer channels, or one or more LOSFE defects, or one or
-//			more RDI defects, or one or more LPR-FE defects. (R) (mandatory) (2-bytes)
+//			This attribute counts 1-s intervals with one or more far end block error (FEBE) anomalies summed
+//			over all transmitted bearer channels, or one or more LOSFE defects, or one or more RDI defects,
+//			or one or more LPR-FE defects. (R) (mandatory) (2-bytes)
 //
 //		Severely Errored Seconds
+//			This attribute counts severely errored seconds (SES-LFE). An SES is declared if, during a 1-s
+//			interval, 18 or more FEBE anomalies were reported across the totality of bearer channels, or
+//			there were one or more far-end LOS defects, one or more RDI defects or one or more LPRFE
+//			defects.
+//
+//			If the relevant Recommendation ([ITUT G.992.3], [ITUT G.992.5] or [ITUT G.993.2]) supports a 1-s
+//			normalized CRC-8 anomaly counter increment, the 1-s SES counter follows this value instead of
+//			counting FEBE anomalies directly.
+//
+//			If a CRC is applied for multiple bearer channels, then each related FEBE anomaly is counted only
+//			once for the whole set of related bearer channels.
+//
 //			(R) (mandatory) (2-bytes)
 //
 //		Fec Seconds
-//			FEC seconds: This attribute counts seconds during which there was an FEC anomaly. (R)
-//			(mandatory) (2-bytes)
+//			This attribute counts seconds during which there was an FEC anomaly. (R) (mandatory) (2-bytes)
 //
 //		Unavailable Seconds
+//			The far-end xDSL termination becomes unavailable at the onset of 10 contiguous SES-LFEs. The 10
+//			SES-LFEs are included in unavailable time. Once unavailable, the far-end line becomes available
+//			at the onset of 10 contiguous seconds with no SES-LFEs. The 10-s with no SES-LFEs are excluded
+//			from unavailable time. Some attribute counts are inhibited during unavailability - see clause
+//			7.2.7.13 of [ITUT G.997.1].
+//
 //			(R) (mandatory) (2-bytes)
 //
+//			This attribute counts 1-s intervals during which the far-end xDSL termination is unavailable.
+//
 //		Leftr Defect Seconds
 //			"leftr" defect seconds: If retransmission is used, this parameter is a count of the seconds with
 //			a near-end ''leftr'' defect present - see clause 7.2.1.1.6 of [ITUT-G.997.1]. (R) (optional)
diff --git a/generated/xg-pondownstreammanagementperformancemonitoringhistorydata.go b/generated/xg-pondownstreammanagementperformancemonitoringhistorydata.go
index 53e549d..3245441 100644
--- a/generated/xg-pondownstreammanagementperformancemonitoringhistorydata.go
+++ b/generated/xg-pondownstreammanagementperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // XgPonDownstreamManagementPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity XG-PON downstream management performance monitoring history data
-const XgPonDownstreamManagementPerformanceMonitoringHistoryDataClassID ClassID = ClassID(345)
+const XgPonDownstreamManagementPerformanceMonitoringHistoryDataClassID = ClassID(345) // 0x0159
 
 var xgpondownstreammanagementperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// XgPonDownstreamManagementPerformanceMonitoringHistoryData (class ID #345)
+// XgPonDownstreamManagementPerformanceMonitoringHistoryData (Class ID: #345 / 0x0159)
 //	This ME collects PM data associated with the XG-PON TC layer. It collects counters associated
 //	with downstream PLOAM and OMCI messages.
 //
@@ -42,13 +42,11 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the ANI-G. (R, set-by-create)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the ANI-G. (R, set-by-create) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
@@ -61,17 +59,17 @@
 //			(4-bytes)
 //
 //		Downstream Ploam Messages Count
-//			Downstream PLOAM messages count: This attribute counts PLOAM messages received, either directed
-//			to this ONU or broadcast to all ONUs. (R) (optional) (4-bytes)
+//			This attribute counts PLOAM messages received, either directed to this ONU or broadcast to all
+//			ONUs. (R) (optional) (4-bytes)
 //
 //		Profile Messages Received
-//			Profile messages received: This attribute counts the number of profile messages received, either
-//			directed to this ONU or broadcast to all ONUs. In [ITU-T G.9807.1], this attribute is used for
-//			received burst_profile message count.  (R) (optional) (4-bytes)
+//			This attribute counts the number of profile messages received, either directed to this ONU or
+//			broadcast to all ONUs. In [ITU-T G.9807.1], this attribute is used for received burst_profile
+//			message count.  (R) (optional) (4-bytes)
 //
 //		Ranging_Time Messages Received
-//			Ranging_time messages received: This attribute counts the number of ranging_time messages
-//			received, either directed to this ONU or broadcast to all ONUs. (R) (mandatory) (4-bytes)
+//			This attribute counts the number of ranging_time messages received, either directed to this ONU
+//			or broadcast to all ONUs. (R) (mandatory) (4-bytes)
 //
 //		Deactivate_Onu_Id Messages Received
 //			Deactivate_ONU-ID messages received: This attribute counts the number of deactivate_ONU-ID
@@ -79,41 +77,40 @@
 //			messages do not reset this counter. (R) (optional) (4-bytes)
 //
 //		Disable_Serial_Number Messages Received
-//			Disable_serial_number messages received: This attribute counts the number of
-//			disable_serial_number messages received, whose serial number specified this ONU. (R) (optional)
-//			(4-bytes)
+//			This attribute counts the number of disable_serial_number messages received, whose serial number
+//			specified this ONU. (R) (optional) (4-bytes)
 //
 //		Request_Registration Messages Received
-//			Request_registration messages received: This attribute counts the number of request_registration
-//			messages received. (R) (optional) (4-bytes)
+//			This attribute counts the number of request_registration messages received. (R) (optional)
+//			(4-bytes)
 //
 //		Assign_Alloc_Id Messages Received
 //			Assign_alloc-ID messages received: This attribute counts the number of assign_alloc-ID messages
 //			received. (R) (optional) (4-bytes)
 //
 //		Key_Control Messages Received
-//			Key_control messages received: This attribute counts the number of key_control messages
-//			received, either directed to this ONU or broadcast to all ONUs. (R) (optional) (4-bytes)
+//			This attribute counts the number of key_control messages received, either directed to this ONU
+//			or broadcast to all ONUs. (R) (optional) (4-bytes)
 //
 //		Sleep_Allow Messages Received
-//			Sleep_allow messages received: This attribute counts the number of sleep_allow messages
-//			received, either directed to this ONU or broadcast to all ONUs. (R) (optional) (4-bytes)
+//			This attribute counts the number of sleep_allow messages received, either directed to this ONU
+//			or broadcast to all ONUs. (R) (optional) (4-bytes)
 //
 //		Baseline Omci Messages Received Count
-//			Baseline OMCI messages received count: This attribute counts the number of OMCI messages
-//			received in the baseline message format. (R) (optional) (4-bytes)
+//			This attribute counts the number of OMCI messages received in the baseline message format. (R)
+//			(optional) (4-bytes)
 //
 //		Extended Omci Messages Received Count
-//			Extended OMCI messages received count: This attribute counts the number of OMCI messages
-//			received in the extended message format. (R) (optional) (4-bytes)
+//			This attribute counts the number of OMCI messages received in the extended message format. (R)
+//			(optional) (4-bytes)
 //
 //		Assign_Onu_Id Messages Received
 //			Assign_ONU-ID messages received: This attribute counts the number of assign_ONU-ID messages
 //			received since the last re-boot. (R) (optional) (4-bytes)
 //
 //		Omci Mic Error Count
-//			OMCI MIC error count: This attribute counts MIC errors detected in OMCI messages directed to
-//			this ONU. (R) (optional) (4-bytes)
+//			This attribute counts MIC errors detected in OMCI messages directed to this ONU. (R) (optional)
+//			(4-bytes)
 //
 type XgPonDownstreamManagementPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/xg-pontcperformancemonitoringhistorydata.go b/generated/xg-pontcperformancemonitoringhistorydata.go
index e67e9f6..4c7a0f9 100644
--- a/generated/xg-pontcperformancemonitoringhistorydata.go
+++ b/generated/xg-pontcperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // XgPonTcPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity XG-PON TC performance monitoring history data
-const XgPonTcPerformanceMonitoringHistoryDataClassID ClassID = ClassID(344)
+const XgPonTcPerformanceMonitoringHistoryDataClassID = ClassID(344) // 0x0158
 
 var xgpontcperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// XgPonTcPerformanceMonitoringHistoryData (class ID #344)
+// XgPonTcPerformanceMonitoringHistoryData (Class ID: #344 / 0x0158)
 //	This ME collects PM data associated with the XG-PON TC layer.
 //
 //	For a complete discussion of generic PM architecture, refer to clause I.4.
@@ -41,30 +41,27 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the ANI-G. (R, set-by-create)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the ANI-G. (R, set-by-create) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 ME that
 //			contains PM threshold values. (R,-W, set-by-create) (mandatory) (2-bytes)
 //
 //		Psbd Hec Error Count
-//			PSBd HEC error count: This attribute counts HEC errors in any of the fields of the downstream
-//			physical sync block. (R) (optional) (4-bytes)
-//
-//		Xgtc Hec Error Count
-//			XGTC HEC error count: This attribute counts HEC errors detected in the XGTC header. In [ITU-T
-//			G.9807.1], this attribute is used for framing sublayer (FS) HEC error count management. (R)
+//			This attribute counts HEC errors in any of the fields of the downstream physical sync block. (R)
 //			(optional) (4-bytes)
 //
+//		Xgtc Hec Error Count
+//			This attribute counts HEC errors detected in the XGTC header. In [ITU-T G.9807.1], this
+//			attribute is used for framing sublayer (FS) HEC error count management. (R) (optional) (4-bytes)
+//
 //		Unknown Profile Count
-//			Unknown profile count: This attribute counts the number of grants received whose specified
-//			profile was not known to the ONU. (R) (optional) (4-bytes)
+//			This attribute counts the number of grants received whose specified profile was not known to the
+//			ONU. (R) (optional) (4-bytes)
 //
 //		Transmitted Xg_Pon Encapsulation Method Xgem Frames
 //			Transmitted XG-PON encapsulation method (XGEM) frames: This attribute counts the number of non-
@@ -72,20 +69,35 @@
 //			XGEM frame and is counted as such. (R) (mandatory) (4 bytes)
 //
 //		Fragment Xgem Frames
-//			Fragment XGEM frames: This attribute counts the number of XGEM frames that represent fragmented
-//			SDUs, as indicated by the LF bit-= 0. (R) (optional) (4-bytes)
+//			This attribute counts the number of XGEM frames that represent fragmented SDUs, as indicated by
+//			the LF bit-= 0. (R) (optional) (4-bytes)
 //
 //		Xgem Hec Lost Words Count
-//			XGEM HEC lost words count: This attribute counts the number of 4-byte words lost because of an
-//			XGEM frame HEC error. In general, all XGTC payload following the error is lost, until the next
-//			PSBd event. (R) (optional) (4 bytes)
+//			This attribute counts the number of 4-byte words lost because of an XGEM frame HEC error. In
+//			general, all XGTC payload following the error is lost, until the next PSBd event. (R) (optional)
+//			(4 bytes)
 //
 //		Xgem Key Errors
+//			This attribute counts the number of downstream XGEM frames received with an invalid key
+//			specification. The key may be invalid for several reasons, among which are:
+//
+//			a)	GEM port provisioned for clear text and key index not equal to 00;
+//
+//			b)	no multicast key of the specified key index has been provided via the OMCI for a multicast
+//			GEM port;
+//
+//			c)	no unicast key of the specified key index has been successfully negotiated (see clause 15.5
+//			of [ITU-T G.987.3] or clause C.15.5 of [ITU-T G.9807.1] for key negotiation state machine);
+//
+//			d)	GEM port specified to be encrypted and key index-= 00;
+//
+//			e)	key index-= 11, a reserved value.
+//
 //			(R) (mandatory) (4 bytes)
 //
 //		Xgem Hec Error Count
-//			XGEM HEC error count: This attribute counts the number of instances of an XGEM frame HEC error.
-//			(R) (mandatory) (4 bytes)
+//			This attribute counts the number of instances of an XGEM frame HEC error. (R) (mandatory) (4
+//			bytes)
 //
 //		Transmitted Bytes In Non_Idle Xgem Frames
 //			Transmitted bytes in non-idle XGEM frames: This attribute counts the number of transmitted bytes
@@ -100,12 +112,11 @@
 //			transitions from O5.1 to O6. (R) (optional) (4-bytes)
 //
 //		Lods Event Restored Count
-//			LODS event restored count: This attribute counts the number of LODS cleared events. (R)
-//			(optional) (4-bytes)
+//			This attribute counts the number of LODS cleared events. (R) (optional) (4-bytes)
 //
 //		Onu Reactivation By Lods Events
-//			ONU reactivation by LODS events: This attribute counts the number of LODS events resulting in
-//			ONU reactivation without synchronization being reacquired. (R) (optional) (4-bytes)
+//			This attribute counts the number of LODS events resulting in ONU reactivation without
+//			synchronization being reacquired. (R) (optional) (4-bytes)
 //
 type XgPonTcPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/xg-ponupstreammanagementperformancemonitoringhistorydata.go b/generated/xg-ponupstreammanagementperformancemonitoringhistorydata.go
index 148af8d..6b44c68 100644
--- a/generated/xg-ponupstreammanagementperformancemonitoringhistorydata.go
+++ b/generated/xg-ponupstreammanagementperformancemonitoringhistorydata.go
@@ -27,11 +27,11 @@
 
 // XgPonUpstreamManagementPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
 // Managed entity XG-PON upstream management performance monitoring history data
-const XgPonUpstreamManagementPerformanceMonitoringHistoryDataClassID ClassID = ClassID(346)
+const XgPonUpstreamManagementPerformanceMonitoringHistoryDataClassID = ClassID(346) // 0x015a
 
 var xgponupstreammanagementperformancemonitoringhistorydataBME *ManagedEntityDefinition
 
-// XgPonUpstreamManagementPerformanceMonitoringHistoryData (class ID #346)
+// XgPonUpstreamManagementPerformanceMonitoringHistoryData (Class ID: #346 / 0x015a)
 //	This ME collects PM data associated with the XG-PON TC layer. It counts upstream PLOAM messages
 //	transmitted by the ONU.
 //
@@ -42,13 +42,11 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the ANI-G. (R, set-by-create)
-//			(mandatory) (2-bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the ANI-G. (R, set-by-create) (mandatory) (2-bytes)
 //
 //		Interval End Time
-//			Interval end time: This attribute identifies the most recently finished 15-min interval. (R)
-//			(mandatory) (1-byte)
+//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1-byte)
 //
 //		Threshold Data 1_2 Id
 //			Threshold data 1/2 ID: No thresholds are defined for this ME. For uniformity with other PM, the
@@ -56,29 +54,25 @@
 //			set-by-create) (mandatory) (2-bytes)
 //
 //		Upstream Ploam Message Count
-//			Upstream PLOAM message count: This attribute counts PLOAM messages transmitted upstream,
-//			excluding acknowledge messages. (R) (optional) (4-bytes)
+//			This attribute counts PLOAM messages transmitted upstream, excluding acknowledge messages. (R)
+//			(optional) (4-bytes)
 //
 //		Serial_Number_Onu Message Count
-//			Serial_number_ONU message count: This attribute counts Serial_number_ONU PLOAM messages
-//			transmitted. (R) (optional) (4-bytes)
+//			This attribute counts Serial_number_ONU PLOAM messages transmitted. (R) (optional) (4-bytes)
 //
 //		Registration Message Count
-//			Registration message count: This attribute counts Registration PLOAM messages transmitted. (R)
-//			(optional) (4-bytes)
+//			This attribute counts Registration PLOAM messages transmitted. (R) (optional) (4-bytes)
 //
 //		Key_Report Message Count
-//			Key_report message count: This attribute counts key_report PLOAM messages transmitted. (R)
-//			(optional) (4-bytes)
+//			This attribute counts key_report PLOAM messages transmitted. (R) (optional) (4-bytes)
 //
 //		Acknowledge Message Count
-//			Acknowledge message count: This attribute counts acknowledge PLOAM messages transmitted. It
-//			includes all forms of acknowledgement (AK), including those transmitted in response to a PLOAM
-//			grant when the ONU has nothing to send. (R) (optional) (4-bytes)
+//			This attribute counts acknowledge PLOAM messages transmitted. It includes all forms of
+//			acknowledgement (AK), including those transmitted in response to a PLOAM grant when the ONU has
+//			nothing to send. (R) (optional) (4-bytes)
 //
 //		Sleep_Request Message Count
-//			Sleep_request message count: This attribute counts sleep_request PLOAM messages transmitted. (R)
-//			(optional) (4-bytes)
+//			This attribute counts sleep_request PLOAM messages transmitted. (R) (optional) (4-bytes)
 //
 type XgPonUpstreamManagementPerformanceMonitoringHistoryData struct {
 	ManagedEntityDefinition
diff --git a/generated/xtudatagatheringconfiguration.go b/generated/xtudatagatheringconfiguration.go
index ce758fc..33e78c5 100644
--- a/generated/xtudatagatheringconfiguration.go
+++ b/generated/xtudatagatheringconfiguration.go
@@ -27,11 +27,11 @@
 
 // XtuDataGatheringConfigurationClassID is the 16-bit ID for the OMCI
 // Managed entity xTU data gathering configuration
-const XtuDataGatheringConfigurationClassID ClassID = ClassID(413)
+const XtuDataGatheringConfigurationClassID = ClassID(413) // 0x019d
 
 var xtudatagatheringconfigurationBME *ManagedEntityDefinition
 
-// XtuDataGatheringConfiguration (class ID #413)
+// XtuDataGatheringConfiguration (Class ID: #413 / 0x019d)
 //	This ME defines configurations specific to data gathering.
 //
 //	An instance of this ME is created and deleted by the OLT.
@@ -42,9 +42,9 @@
 //
 //	Attributes
 //		Managed Entity Id
-//			Managed entity ID: This attribute uniquely identifies each instance of this ME. Through an
-//			identical ID, this ME is implicitly linked to an instance of the PPTP xDSL UNI part 1 ME.
-//			(R,-set-by-create) (mandatory) (2 bytes)
+//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
+//			implicitly linked to an instance of the PPTP xDSL UNI part 1 ME. (R,-set-by-create) (mandatory)
+//			(2 bytes)
 //
 //		Logging Depth Event Percentage Per Event _ Vtu_O Logging_Depth_Event_Percentage_Oi Table
 //			Logging depth event percentage per event - VTU-O (LOGGING_DEPTH_EVENT_PERCENTAGE_Oi) table: This
diff --git a/get.go b/get.go
new file mode 100644
index 0000000..0214907
--- /dev/null
+++ b/get.go
@@ -0,0 +1,380 @@
+/*
+ * 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"
+	"github.com/google/gopacket"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+type GetRequest struct {
+	MeBasePacket
+	AttributeMask uint16
+}
+
+func (omci *GetRequest) String() string {
+	return fmt.Sprintf("%v, Mask: %#x",
+		omci.MeBasePacket.String(), omci.AttributeMask)
+}
+
+// LayerType returns LayerTypeGetRequest
+func (omci *GetRequest) LayerType() gopacket.LayerType {
+	return LayerTypeGetRequest
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *GetRequest) CanDecode() gopacket.LayerClass {
+	return LayerTypeGetRequest
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *GetRequest) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6 + 2
+	} else {
+		hdrSize = 4 + 2
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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")
+	}
+	if omci.Extended {
+		if len(data) < 8 {
+			p.SetTruncated()
+			return errors.New("frame too small")
+		}
+		omci.AttributeMask = binary.BigEndian.Uint16(data[6:])
+	} else {
+		omci.AttributeMask = binary.BigEndian.Uint16(data[4:])
+	}
+	return nil
+}
+
+func decodeGetRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetRequest{}
+	omci.MsgLayerType = LayerTypeGetRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+func decodeGetRequestExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetRequest{}
+	omci.MsgLayerType = LayerTypeGetRequest
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Get Request message
+func (omci *GetRequest) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	maskOffset := 0
+	if omci.Extended {
+		maskOffset = 2
+	}
+	bytes, err := b.AppendBytes(2 + maskOffset)
+	if err != nil {
+		return err
+	}
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, uint16(2))
+	}
+	binary.BigEndian.PutUint16(bytes[maskOffset:], omci.AttributeMask)
+	return nil
+}
+
+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)
+}
+
+// LayerType returns LayerTypeGetResponse
+func (omci *GetResponse) LayerType() gopacket.LayerType {
+	return LayerTypeGetResponse
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *GetResponse) CanDecode() gopacket.LayerClass {
+	return LayerTypeGetResponse
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *GetResponse) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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, 4+3)
+	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")
+	}
+	if omci.Extended {
+		if len(data) < 13 {
+			p.SetTruncated()
+			return errors.New("frame too small")
+		}
+		omci.Result = me.Results(data[6])
+		omci.AttributeMask = binary.BigEndian.Uint16(data[7:])
+
+		// If Attribute failed or Unknown, decode optional attribute mask
+		if omci.Result == me.AttributeFailure {
+			omci.UnsupportedAttributeMask = binary.BigEndian.Uint16(data[9:])
+			omci.FailedAttributeMask = binary.BigEndian.Uint16(data[11:])
+		}
+	} else {
+		omci.Result = me.Results(data[4])
+		omci.AttributeMask = binary.BigEndian.Uint16(data[5:])
+
+		// 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])
+		}
+	}
+	// 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.
+	firstOctet := 7
+	lastOctet := 36
+	if omci.Extended {
+		firstOctet = 13
+		lastOctet = len(data)
+	}
+
+	switch omci.Result {
+	case me.ProcessingError, me.NotSupported, me.UnknownEntity, me.UnknownInstance, me.DeviceBusy:
+		return nil // Done (do not try and decode attributes)
+
+	case me.AttributeFailure:
+		if !omci.Extended {
+			lastOctet = 32
+		}
+	}
+	omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask,
+		data[firstOctet:lastOctet], p, byte(GetResponseType))
+	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
+	}
+	return errors.New("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)
+}
+
+func decodeGetResponseExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetResponse{}
+	omci.MsgLayerType = LayerTypeGetResponse
+	omci.Extended = true
+	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")
+	}
+	resultOffset := 0
+	attributeErrExtra := 0
+
+	if omci.Extended {
+		resultOffset = 2
+		attributeErrExtra = 4 // Attribute mask + attribute error masks
+	}
+	// Space for result + mask (both types) + (len & error masks if extended)
+	buffer, err := b.AppendBytes(3 + resultOffset + attributeErrExtra)
+	if err != nil {
+		return err
+	}
+	// Save result and initial mask. Other header fields updated after
+	// attribute copy
+	buffer[resultOffset] = byte(omci.Result)
+	binary.BigEndian.PutUint16(buffer[resultOffset+1:], omci.AttributeMask)
+
+	// Validate all attributes requested support read
+	for attrName := range omci.Attributes {
+		var attr *me.AttributeDefinition
+		attr, err = me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
+		if err != nil {
+			return err
+		}
+		if attr.Index != 0 && (attr.Mask&omci.AttributeMask != 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:
+		if omci.Extended {
+			// Minimum length is 7 for extended an need to write error masks
+			binary.BigEndian.PutUint16(buffer, uint16(7))
+			binary.BigEndian.PutUint32(buffer[resultOffset+3:], 0)
+		}
+		break
+
+	case me.Success, me.AttributeFailure:
+		// TODO: Baseline only supported at this time)
+		var available int
+		if omci.Extended {
+			available = MaxExtendedLength - 18 - 4 // Less: header, mic
+		} else {
+			available = MaxBaselineLength - 11 - 4 - 8 // Less: header, failed attributes, length, mic
+		}
+		// Serialize to temporary buffer if we may need to reset values due to
+		// recoverable truncation errors
+		attributeBuffer := gopacket.NewSerializeBuffer()
+		var failedMask uint16
+		err, failedMask = meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask,
+			attributeBuffer, byte(GetResponseType), available, opts.FixLengths)
+
+		if err != nil {
+			return err
+		}
+		if failedMask != 0 {
+			// Not all attributes would fit
+			omci.FailedAttributeMask |= failedMask
+			omci.AttributeMask &= ^failedMask
+			omci.Result = me.AttributeFailure
+
+			// Adjust already recorded values
+			buffer[resultOffset] = byte(omci.Result)
+			binary.BigEndian.PutUint16(buffer[resultOffset+1:], omci.AttributeMask)
+		}
+		if omci.Extended {
+			// Set length and any failure masks
+			binary.BigEndian.PutUint16(buffer, uint16(len(attributeBuffer.Bytes())+7))
+
+			if omci.Result == me.AttributeFailure {
+				binary.BigEndian.PutUint16(buffer[resultOffset+3:], omci.UnsupportedAttributeMask)
+				binary.BigEndian.PutUint16(buffer[resultOffset+5:], omci.FailedAttributeMask)
+			} else {
+				binary.BigEndian.PutUint32(buffer[resultOffset+3:], 0)
+			}
+		}
+		// Copy over attributes to the original serialization buffer
+		var newSpace []byte
+
+		newSpace, err = b.AppendBytes(len(attributeBuffer.Bytes()))
+		if err != nil {
+			return err
+		}
+		copy(newSpace, attributeBuffer.Bytes())
+
+		if !omci.Extended {
+			// Calculate space left. Max  - msgType header - OMCI trailer - spacedUsedSoFar
+			bytesLeft := MaxBaselineLength - 4 - 8 - len(b.Bytes())
+
+			var remainingBytes []byte
+			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
+}
diff --git a/get_test.go b/get_test.go
new file mode 100644
index 0000000..a76ff8f
--- /dev/null
+++ b/get_test.go
@@ -0,0 +1,611 @@
+/*
+ * 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_test
+
+import (
+	"encoding/base64"
+	"encoding/binary"
+	"fmt"
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/stretchr/testify/assert"
+	"strings"
+	"testing"
+)
+
+func TestGetRequestDecode(t *testing.T) {
+	goodMessage := "035e490a01070000004400000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeGetRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x035e), omciMsg.TransactionID)
+	assert.Equal(t, GetRequestType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeGetRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*GetRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeGetRequest, request.LayerType())
+	assert.Equal(t, LayerTypeGetRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestGetRequestSerialize(t *testing.T) {
+	goodMessage := "035e490a01070000004400000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x035e,
+		MessageType:   GetRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &GetRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.AniGClassID,
+			EntityInstance: uint16(0),
+		},
+		AttributeMask: uint16(0x0044),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestGetRequestZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0000,
+		MessageType:   GetRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &GetRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.AniGClassID,
+			EntityInstance: uint16(0),
+		},
+		AttributeMask: uint16(0x0044),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestGetResponseDecode(t *testing.T) {
+	goodMessage := "035e290a01070000000044dbcb05f10000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, uint16(0x035e), omciMsg.TransactionID)
+	assert.Equal(t, GetResponseType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeGetResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*GetResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeGetResponse, response.LayerType())
+	assert.Equal(t, LayerTypeGetResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, response.Result, me.Success)
+	assert.Equal(t, response.AttributeMask, uint16(0x0044))
+	assert.Equal(t, response.Attributes["TransmitOpticalLevel"], uint16(0x05f1))
+	assert.Equal(t, response.Attributes["OpticalSignalLevel"], uint16(0xdbcb))
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestGetResponseSerialize(t *testing.T) {
+	goodMessage := "035e290a01070000000044dbcb05f10000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x035e,
+		MessageType:   GetResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &GetResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.AniGClassID,
+			EntityInstance: uint16(0),
+		},
+		Result:        0,
+		AttributeMask: uint16(0x0044),
+		Attributes: me.AttributeValueMap{
+			"TransmitOpticalLevel": uint16(0x05f1),
+			"OpticalSignalLevel":   uint16(0xdbcb)},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestGetResponseZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   GetResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &GetResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.AniGClassID,
+			EntityInstance: uint16(0),
+		},
+		Result:        0,
+		AttributeMask: uint16(0x0044),
+		Attributes: me.AttributeValueMap{
+			"TransmitOpticalLevel": uint16(0x05f1),
+			"OpticalSignalLevel":   uint16(0xdbcb)},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+///////////////////////////////////////////////////////////////////////
+// Packet definitions for attributes of various types/sizes
+func toOctets(str string) []byte {
+	data, err := base64.StdEncoding.DecodeString(str)
+	if err != nil {
+		panic(fmt.Sprintf("Invalid Base-64 string: '%v'", str))
+	}
+	return data
+}
+
+func TestGetResponseSerializeTruncationFailure(t *testing.T) {
+	// Too much data and 'fix-length' is not specified.  This response has 26
+	// octets in the requested data, but only 25 octets available
+
+	omciLayer := &OMCI{
+		TransactionID: 0x035e,
+		MessageType:   GetResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &GetResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuGClassID,
+			EntityInstance: uint16(0),
+		},
+		Result:        0,
+		AttributeMask: uint16(0xE000),
+		Attributes: me.AttributeValueMap{
+			"VendorId":     toOctets("ICAgIA=="),
+			"Version":      toOctets("MAAAAAAAAAAAAAAAAAA="),
+			"SerialNumber": toOctets("AAAAAAAAAAA="),
+		},
+	}
+	// Test serialization and verify truncation failure
+	var options gopacket.SerializeOptions
+	options.FixLengths = false
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+	assert.IsType(t, &me.MessageTruncatedError{}, err)
+}
+
+func TestGetResponseSerializeTruncationButOkay(t *testing.T) {
+	// Too much data and 'fix-length' is specified so it packs as much as
+	// possible and adjusts the failure masks
+
+	omciLayer := &OMCI{
+		TransactionID: 0x035e,
+		MessageType:   GetResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	response := &GetResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuGClassID,
+			EntityInstance: uint16(0),
+		},
+		Result:        0,
+		AttributeMask: uint16(0xE000),
+		Attributes: me.AttributeValueMap{
+			"VendorId":     toOctets("ICAgIA=="),
+			"Version":      toOctets("MAAAAAAAAAAAAAAAAAA="),
+			"SerialNumber": toOctets("AAAAAAAAAAA="),
+		},
+	}
+	// Test serialization and verify truncation failure
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, response)
+	assert.NoError(t, err)
+
+	// Now deserialize it and see if we have the proper result (Attribute Failure)
+	// and a non-zero failed mask
+	responsePacket := buffer.Bytes()
+	packet := gopacket.NewPacket(responsePacket, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer2 := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer2)
+
+	omciMsg2, ok := omciLayer2.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, LayerTypeOMCI, omciMsg2.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg2.CanDecode())
+	assert.Equal(t, LayerTypeGetResponse, omciMsg2.NextLayerType())
+	assert.Equal(t, omciMsg2.TransactionID, omciLayer.TransactionID)
+	assert.Equal(t, GetResponseType, omciLayer.MessageType)
+	assert.Equal(t, BaselineIdent, omciLayer.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciLayer.Length)
+
+	msgLayer2 := packet.Layer(LayerTypeGetResponse)
+	assert.NotNil(t, msgLayer2)
+
+	response2, ok2 := msgLayer2.(*GetResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response2)
+	assert.Equal(t, LayerTypeGetResponse, response2.LayerType())
+	assert.Equal(t, LayerTypeGetResponse, response2.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response2.NextLayerType())
+	assert.Equal(t, me.AttributeFailure, response2.Result)
+	assert.NotZero(t, response2.AttributeMask)
+	assert.NotZero(t, response2.FailedAttributeMask)
+	assert.Zero(t, response2.UnsupportedAttributeMask)
+}
+
+func TestGetResponseTableFailedAttributesDecode(t *testing.T) {
+	// This is a GET Response with failed and unsupported attributes
+	// TODO:Implement
+}
+
+func TestGetResponseTableFailedAttributesSerialize(t *testing.T) {
+	// This is a GET Response with failed and unsupported attributes
+	// TODO:Implement
+}
+
+func TestGetResponseTableAttributeDecode(t *testing.T) {
+	// This is a GET Response for a table attribute. It should return the attribute
+	// size as a uint16.
+	// TODO:Implement
+}
+
+func TestGetResponseTableAttributeSerialize(t *testing.T) {
+	// This is a GET Response for a table attribute. It should return the attribute
+	// size as a uint16.
+	// TODO:Implement
+}
+
+func TestExtendedGetRequestDecode(t *testing.T) {
+	//ONU-2G: 257
+	goodMessage := "035e490b010100000002fffc"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeGetRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x035e), omciMsg.TransactionID)
+	assert.Equal(t, GetRequestType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(2), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeGetRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*GetRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeGetRequest, request.LayerType())
+	assert.Equal(t, LayerTypeGetRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+
+	//ONU-2G: 257
+	assert.Equal(t, me.Onu2GClassID, request.EntityClass)
+	assert.Equal(t, uint16(0), request.EntityInstance)
+	assert.Equal(t, uint16(0xfffc), request.AttributeMask)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedGetRequestDecodeTruncated(t *testing.T) {
+	goodMessage := "035e490b010100000002ff"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	failure := packet.ErrorLayer()
+	assert.NotNil(t, failure)
+
+	decodeFailure, ok := failure.(*gopacket.DecodeFailure)
+	assert.NotNil(t, decodeFailure)
+	assert.True(t, ok)
+	assert.NotNil(t, decodeFailure.String())
+	assert.True(t, len(decodeFailure.String()) > 0)
+
+	metadata := packet.Metadata()
+	assert.NotNil(t, metadata)
+	assert.True(t, metadata.Truncated)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedGetRequestSerialize(t *testing.T) {
+	goodMessage := "035e490b010100000002fffc"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x035e,
+		MessageType:      GetRequestType,
+		DeviceIdentifier: ExtendedIdent,
+		// Length parameter is optional for Extended message format serialization
+		// and if present it will be overwritten during the serialization with the
+		// actual value.
+	}
+	request := &GetRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.Onu2GClassID,
+			EntityInstance: uint16(0),
+			Extended:       true,
+		},
+		AttributeMask: uint16(0xfffc),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestExtendedGetResponseDecode(t *testing.T) {
+	attrDef, omciErr := me.GetAttributesDefinitions(me.Onu2GClassID)
+	assert.NotNil(t, attrDef)
+	assert.NotNil(t, omciErr)
+	assert.Equal(t, me.Success, omciErr.StatusCode())
+
+	attributes := []interface{}{
+		toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAA="), //  1: MultiByteField - "EquipmentId"  (20 zeros)
+		byte(0xb4),                               //  2: ByteField   - "OpticalNetworkUnitManagementAndControlChannelOmccVersion"
+		uint16(0x1234),                           //  3: Uint16Field - "VendorProductCode"
+		byte(1),                                  //  4: ByteField   - "SecurityCapability"
+		byte(1),                                  //  5: ByteField   - "SecurityMode"
+		uint16(0x5678),                           //  6: Uint16Field - "TotalPriorityQueueNumber"
+		byte(0x44),                               //  7: ByteField   - "TotalTrafficSchedulerNumber"
+		byte(1),                                  //  8: ByteField   - "Deprecated"
+		uint16(0x55aa),                           //  9: Uint16Field - "TotalGemPortIdNumber"
+		uint32(0xC4108011),                       // 10: Uint32Field - "Sysuptime"
+		uint16(0x6),                              // 11: Uint16Field - "ConnectivityCapability"
+		byte(6),                                  // 12: ByteField   - "CurrentConnectivityMode"
+		uint16(2),                                // 13: Uint16Field - "QualityOfServiceQosConfigurationFlexibility"
+		uint16(0x1234),                           // 14: Uint16Field - "PriorityQueueScaleFactor"
+	}
+	attributeData := make([]byte, 0)
+
+	// Walk through all attributes and encode them
+	for _, value := range attributes {
+		//attrDef, err := meDef.GetAttributeByIndex(index)
+		var buf []byte
+		u8, ok := value.(byte)
+		if ok {
+			buf = []byte{u8}
+		} else {
+			u16, ok := value.(uint16)
+			if ok {
+				buf = make([]byte, 2)
+				binary.BigEndian.PutUint16(buf, u16)
+			} else {
+				u32, ok := value.(uint32)
+				if ok {
+					buf = make([]byte, 4)
+					binary.BigEndian.PutUint32(buf, u32)
+				} else {
+					bytes, ok := value.([]byte)
+					if ok {
+						buf = bytes
+					} else {
+						assert.True(t, false) // Unknown attribute type
+					}
+				}
+			}
+		}
+		attributeData = append(attributeData, buf...)
+	}
+	attributeMask := 0xfffc
+	msgLength := len(attributeData) + 7
+	// Results is 0 ("00"), and the two optional attribute masks are 0 ("00000000") as well
+	goodMessage := "035e290b01010000" + fmt.Sprintf("%04x", msgLength) +
+		"00" + fmt.Sprintf("%04x", attributeMask) + "00000000" + packetToString(attributeData)
+
+	data, err := stringToPacket(goodMessage)
+	assert.NotNil(t, data)
+	assert.Nil(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeGetResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x035e), omciMsg.TransactionID)
+	assert.Equal(t, GetResponseType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(msgLength), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeGetResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*GetResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeGetResponse, response.LayerType())
+	assert.Equal(t, LayerTypeGetResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, me.Success, response.Result)
+	assert.Equal(t, uint16(attributeMask), response.AttributeMask)
+	assert.Equal(t, uint16(0), response.FailedAttributeMask)
+	assert.Equal(t, uint16(0), response.UnsupportedAttributeMask)
+
+	assert.Equal(t, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAA="), response.Attributes["EquipmentId"])
+	assert.Equal(t, byte(0xb4), response.Attributes["OpticalNetworkUnitManagementAndControlChannelOmccVersion"])
+	assert.Equal(t, uint16(0x1234), response.Attributes["VendorProductCode"])
+	assert.Equal(t, byte(1), response.Attributes["SecurityCapability"])
+	assert.Equal(t, byte(1), response.Attributes["SecurityMode"])
+	assert.Equal(t, uint16(0x5678), response.Attributes["TotalPriorityQueueNumber"])
+	assert.Equal(t, byte(0x44), response.Attributes["TotalTrafficSchedulerNumber"])
+	assert.Equal(t, byte(1), response.Attributes["Deprecated"])
+	assert.Equal(t, uint16(0x55aa), response.Attributes["TotalGemPortIdNumber"])
+	assert.Equal(t, uint32(0xC4108011), response.Attributes["Sysuptime"])
+	assert.Equal(t, uint16(0x6), response.Attributes["ConnectivityCapability"])
+	assert.Equal(t, byte(6), response.Attributes["CurrentConnectivityMode"])
+	assert.Equal(t, uint16(2), response.Attributes["QualityOfServiceQosConfigurationFlexibility"])
+	assert.Equal(t, uint16(0x1234), response.Attributes["PriorityQueueScaleFactor"])
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedGetResponseSerialize(t *testing.T) {
+	goodMessage := "035e290b01010000003100fffc" +
+		"000000000000000000000000000000000000000000000000" +
+		"b4123401015678440155aac410801100060600021234"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x035e,
+		MessageType:      GetResponseType,
+		DeviceIdentifier: ExtendedIdent,
+		// Length parameter is optional for Extended message format serialization
+		// and if present it will be overwritten during the serialization with the
+		// actual value.
+	}
+	request := &GetResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.Onu2GClassID,
+			EntityInstance: uint16(0),
+			Extended:       true,
+		},
+		Result:        0,
+		AttributeMask: uint16(0xfffc),
+		Attributes: me.AttributeValueMap{
+			"EquipmentId": toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
+			"OpticalNetworkUnitManagementAndControlChannelOmccVersion": byte(0xb4),
+			"VendorProductCode":                           uint16(0x1234),
+			"SecurityCapability":                          byte(1),
+			"SecurityMode":                                byte(1),
+			"TotalPriorityQueueNumber":                    uint16(0x5678),
+			"TotalTrafficSchedulerNumber":                 byte(0x44),
+			"Deprecated":                                  byte(1),
+			"TotalGemPortIdNumber":                        uint16(0x55aa),
+			"Sysuptime":                                   uint32(0xC4108011),
+			"ConnectivityCapability":                      uint16(0x6),
+			"CurrentConnectivityMode":                     byte(6),
+			"QualityOfServiceQosConfigurationFlexibility": uint16(2),
+			"PriorityQueueScaleFactor":                    uint16(0x1234),
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
diff --git a/getcurrent.go b/getcurrent.go
new file mode 100644
index 0000000..33600e9
--- /dev/null
+++ b/getcurrent.go
@@ -0,0 +1,348 @@
+/*
+ * 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"
+	"github.com/google/gopacket"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+type GetCurrentDataRequest struct {
+	MeBasePacket
+	AttributeMask uint16
+}
+
+func (omci *GetCurrentDataRequest) String() string {
+	return fmt.Sprintf("%v, Attribute Mask: %#x",
+		omci.MeBasePacket.String(), omci.AttributeMask)
+}
+
+// LayerType returns LayerTypeGetCurrentDataRequest
+func (omci *GetCurrentDataRequest) LayerType() gopacket.LayerType {
+	return LayerTypeGetCurrentDataRequest
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *GetCurrentDataRequest) CanDecode() gopacket.LayerClass {
+	return LayerTypeGetCurrentDataRequest
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *GetCurrentDataRequest) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var offset int
+	if omci.Extended {
+		offset = 6
+	} else {
+		offset = 4
+	}
+	hdrSize := offset + 2
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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[offset:])
+	return nil
+}
+
+func decodeGetCurrentDataRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetCurrentDataRequest{}
+	omci.MsgLayerType = LayerTypeGetCurrentDataRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+func decodeGetCurrentDataRequestExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetCurrentDataRequest{}
+	omci.MsgLayerType = LayerTypeGetCurrentDataRequest
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Get Current Data Request message
+func (omci *GetCurrentDataRequest) SerializeTo(b gopacket.SerializeBuffer, _ 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
+	UnsupportedAttributeMask uint16
+	FailedAttributeMask      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)
+}
+
+// LayerType returns LayerTypeGetCurrentDataResponse
+func (omci *GetCurrentDataResponse) LayerType() gopacket.LayerType {
+	return LayerTypeGetCurrentDataResponse
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *GetCurrentDataResponse) CanDecode() gopacket.LayerClass {
+	return LayerTypeGetCurrentDataResponse
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *GetCurrentDataResponse) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// DecodeFromBytes decodes the given bytes of a Get Current Data Response into this layer
+func (omci *GetCurrentDataResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	var offset, length int
+	if omci.Extended {
+		offset = 6
+		length = 7
+	} else {
+		offset = 4
+		length = 3
+	}
+	hdrSize := offset + length
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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.Result = me.Results(data[offset])
+	omci.AttributeMask = binary.BigEndian.Uint16(data[offset+1:])
+	switch omci.Result {
+	case me.ProcessingError, me.NotSupported, me.UnknownEntity, me.UnknownInstance, me.DeviceBusy:
+		return nil // Done (do not try and decode attributes)
+	case me.AttributeFailure:
+		if omci.Extended {
+			omci.UnsupportedAttributeMask = binary.BigEndian.Uint16(data[offset+3:])
+			omci.FailedAttributeMask = binary.BigEndian.Uint16(data[offset+5:])
+		} else {
+			omci.UnsupportedAttributeMask = binary.BigEndian.Uint16(data[32:])
+			omci.FailedAttributeMask = binary.BigEndian.Uint16(data[34:])
+		}
+	}
+	// 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 in a baseline GET
+	//                   Response. So this behaviour is anticipated here as well
+	//                   and will be allowed in favor of greater interoperability.
+	omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask, data[hdrSize:], p, byte(GetCurrentDataResponseType))
+	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
+	}
+	return errors.New("all Managed Entities have an EntityID attribute")
+}
+
+func decodeGetCurrentDataResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetCurrentDataResponse{}
+	omci.MsgLayerType = LayerTypeGetCurrentDataResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+func decodeGetCurrentDataResponseExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetCurrentDataResponse{}
+	omci.MsgLayerType = LayerTypeGetCurrentDataResponse
+	omci.Extended = true
+	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")
+	}
+	var resultOffset, hdrSize int
+
+	if omci.Extended {
+		resultOffset = 2
+		hdrSize = resultOffset + 1 + 2 + 2 + 2 // length + result + masks
+	} else {
+		resultOffset = 0
+		hdrSize = resultOffset + 1 + 2 // length + result + attr-mask
+	}
+	bytes, err := b.AppendBytes(hdrSize)
+	if err != nil {
+		return err
+	}
+	bytes[resultOffset] = byte(omci.Result)
+	binary.BigEndian.PutUint16(bytes[resultOffset+1:], omci.AttributeMask)
+
+	// Validate all attributes support read
+	for attrName := range omci.Attributes {
+		var attr *me.AttributeDefinition
+		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:
+		if omci.Extended {
+			binary.BigEndian.PutUint16(bytes, 7) // Length
+			binary.BigEndian.PutUint32(bytes[resultOffset+3:], 0)
+		}
+		break
+
+	case me.Success, me.AttributeFailure:
+		var available int
+		if omci.Extended {
+			available = MaxExtendedLength - 10 - 3 - 4 - 4 // Less: header, result+mask, optional-masks mic
+		} else {
+			available = MaxBaselineLength - 8 - 3 - 4 - 8 // hdr, result+mask, optional-masks, trailer
+		}
+		// Serialize to temporary buffer if we may need to reset values due to
+		// recoverable truncation errors
+		attributeBuffer := gopacket.NewSerializeBuffer()
+		var failedMask uint16
+		err, failedMask = meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask,
+			attributeBuffer, byte(GetCurrentDataResponseType), available, opts.FixLengths)
+
+		if err != nil {
+			return err
+		}
+		if failedMask != 0 {
+			// Not all attributes would fit
+			omci.FailedAttributeMask |= failedMask
+			omci.AttributeMask &= ^failedMask
+			omci.Result = me.AttributeFailure
+
+			// Adjust already recorded values
+			bytes[resultOffset] = byte(omci.Result)
+			binary.BigEndian.PutUint16(bytes[resultOffset+1:], omci.AttributeMask)
+		}
+		if omci.Extended {
+			// Set length and any failure masks
+			binary.BigEndian.PutUint16(bytes, uint16(len(attributeBuffer.Bytes())+7))
+
+			if omci.Result == me.AttributeFailure {
+				binary.BigEndian.PutUint16(bytes[resultOffset+3:], omci.UnsupportedAttributeMask)
+				binary.BigEndian.PutUint16(bytes[resultOffset+5:], omci.FailedAttributeMask)
+			} else {
+				binary.BigEndian.PutUint32(bytes[resultOffset+3:], 0)
+			}
+		}
+		// Copy over attributes to the original serialization buffer
+		var newSpace []byte
+
+		newSpace, err = b.AppendBytes(len(attributeBuffer.Bytes()))
+		if err != nil {
+			return err
+		}
+		copy(newSpace, attributeBuffer.Bytes())
+
+		if !omci.Extended {
+			// Calculate space left. Max  - msgType header - OMCI trailer - spacedUsedSoFar
+			bytesLeft := MaxBaselineLength - 4 - 8 - len(b.Bytes())
+
+			var remainingBytes []byte
+			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
+}
diff --git a/getcurrent_test.go b/getcurrent_test.go
new file mode 100644
index 0000000..477f704
--- /dev/null
+++ b/getcurrent_test.go
@@ -0,0 +1,369 @@
+/*
+ * 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_test
+
+import (
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/stretchr/testify/assert"
+	"strings"
+	"testing"
+)
+
+func TestGetCurrentDataRequestDecode(t *testing.T) {
+	goodMessage := "035e5c0a01a90000004400000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeGetCurrentDataRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x035e), omciMsg.TransactionID)
+	assert.Equal(t, GetCurrentDataRequestType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeGetCurrentDataRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*GetCurrentDataRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeGetCurrentDataRequest, request.LayerType())
+	assert.Equal(t, LayerTypeGetCurrentDataRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, me.EthernetFrameExtendedPm64BitClassID, request.EntityClass)
+	assert.Equal(t, uint16(0), request.EntityInstance)
+	assert.Equal(t, uint16(0x0044), request.AttributeMask)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestGetCurrentDataRequestSerialize(t *testing.T) {
+	goodMessage := "035e5c0a01a90000004400000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x035e,
+		MessageType:   GetCurrentDataRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &GetCurrentDataRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.EthernetFrameExtendedPm64BitClassID,
+			EntityInstance: uint16(0),
+		},
+		AttributeMask: uint16(0x0044),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestGetCurrentDataRequestZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   GetCurrentDataRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &GetCurrentDataRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.EthernetFrameExtendedPm64BitClassID,
+			EntityInstance: uint16(0),
+		},
+		AttributeMask: uint16(0x0044),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestGetCurrentDataResponseDecode(t *testing.T) {
+	goodMessage := "035e3c0a01a90000000044123456781234dbcb432187654321dac1000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeGetCurrentDataResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x035e), omciMsg.TransactionID)
+	assert.Equal(t, GetCurrentDataResponseType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeGetCurrentDataResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*GetCurrentDataResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeGetCurrentDataResponse, response.LayerType())
+	assert.Equal(t, LayerTypeGetCurrentDataResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, me.EthernetFrameExtendedPm64BitClassID, response.EntityClass)
+	assert.Equal(t, uint16(0), response.EntityInstance)
+	assert.Equal(t, me.Success, response.Result)
+	assert.Equal(t, uint16(0x0044), response.AttributeMask)
+	assert.Equal(t, uint64(0x123456781234dbcb), response.Attributes["OversizeFrames"])
+	assert.Equal(t, uint64(0x432187654321dac1), response.Attributes["Frames256To511Octets"])
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestGetCurrentDataResponseSerialize(t *testing.T) {
+	goodMessage := "035e3c0a01a90000000044123456781234dbcb432187654321dac10000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x035e,
+		MessageType:   GetCurrentDataResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &GetCurrentDataResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.EthernetFrameExtendedPm64BitClassID,
+			EntityInstance: uint16(0),
+		},
+		Result:        0,
+		AttributeMask: uint16(0x0044),
+		Attributes: me.AttributeValueMap{
+			"OversizeFrames":       uint64(0x123456781234dbcb),
+			"Frames256To511Octets": uint64(0x432187654321dac1),
+			// BroadcastFrames can be supplied but will not be encoded since not in attribute mask.
+			"BroadcastFrames": uint64(0x0123456789abcdef)},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestGetCurrentDataResponseZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   GetCurrentDataResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &GetCurrentDataResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.EthernetFrameExtendedPm64BitClassID,
+			EntityInstance: uint16(0),
+		},
+		Result:        0,
+		AttributeMask: uint16(0x0044),
+		Attributes: me.AttributeValueMap{
+			"OversizeFrames":       uint64(0x123456781234dbcb),
+			"Frames256To511Octets": uint64(0x432187654321dac1),
+			// BroadcastFrames can be supplied but will not be encoded since not in attribute mask.
+			"BroadcastFrames": uint64(0x0123456789abcdef)},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestExtendedGetCurrentDataRequestDecode(t *testing.T) {
+	goodMessage := "035e5c0b0034000100028000"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeGetCurrentDataRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x035e), omciMsg.TransactionID)
+	assert.Equal(t, GetCurrentDataRequestType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(2), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeGetCurrentDataRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*GetCurrentDataRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeGetCurrentDataRequest, request.LayerType())
+	assert.Equal(t, LayerTypeGetCurrentDataRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, me.MacBridgePortPerformanceMonitoringHistoryDataClassID, request.EntityClass)
+	assert.Equal(t, uint16(0x8000), request.AttributeMask)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedGetCurrentDataRequestSerialize(t *testing.T) {
+	goodMessage := "035e5c0b0034000100028000"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x035e,
+		MessageType:      GetCurrentDataRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &GetRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.MacBridgePortPerformanceMonitoringHistoryDataClassID,
+			EntityInstance: uint16(1),
+			Extended:       true,
+		},
+		AttributeMask: uint16(0x8000),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestExtendedGetCurrentDataResponseDecode(t *testing.T) {
+	goodMessage := "035e3c0b0034000100080080000000000010"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeGetCurrentDataResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x035e), omciMsg.TransactionID)
+	assert.Equal(t, GetCurrentDataResponseType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(8), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeGetCurrentDataResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*GetCurrentDataResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeGetCurrentDataResponse, response.LayerType())
+	assert.Equal(t, LayerTypeGetCurrentDataResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, me.MacBridgePortPerformanceMonitoringHistoryDataClassID, response.EntityClass)
+	assert.Equal(t, uint16(1), response.EntityInstance)
+	assert.Equal(t, me.Success, response.Result)
+	assert.Equal(t, uint16(0x8000), response.AttributeMask)
+	assert.Equal(t, uint8(0x10), response.Attributes["IntervalEndTime"])
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedGetCurrentDataResponseSerialize(t *testing.T) {
+	goodMessage := "035e3c0b0034000100080080000000000010"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x035e,
+		MessageType:      GetCurrentDataResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &GetResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.MacBridgePortPerformanceMonitoringHistoryDataClassID,
+			EntityInstance: uint16(1),
+			Extended:       true,
+		},
+		Result:        me.Success,
+		AttributeMask: uint16(0x8000),
+		Attributes: me.AttributeValueMap{
+			"IntervalEndTime": uint8(0x10),
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
diff --git a/getnext.go b/getnext.go
new file mode 100644
index 0000000..1a79bdc
--- /dev/null
+++ b/getnext.go
@@ -0,0 +1,305 @@
+/*
+ * 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"
+	"github.com/google/gopacket"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+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)
+}
+
+// LayerType returns LayerTypeGetNextRequest
+func (omci *GetNextRequest) LayerType() gopacket.LayerType {
+	return LayerTypeGetNextRequest
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *GetNextRequest) CanDecode() gopacket.LayerClass {
+	return LayerTypeGetNextRequest
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *GetNextRequest) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		//start here
+		hdrSize = 6 + 4
+	} else {
+		hdrSize = 4 + 4
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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 attribute.  Issue warning or return error
+	omci.AttributeMask = binary.BigEndian.Uint16(data[hdrSize-4:])
+	omci.SequenceNumber = binary.BigEndian.Uint16(data[hdrSize-2:])
+	return nil
+}
+
+func decodeGetNextRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetNextRequest{}
+	omci.MsgLayerType = LayerTypeGetNextRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+func decodeGetNextRequestExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetNextRequest{}
+	omci.MsgLayerType = LayerTypeGetNextRequest
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Get Next Message Type Request
+func (omci *GetNextRequest) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	maskOffset := 0
+	if omci.Extended {
+		maskOffset = 2
+	}
+	bytes, err := b.AppendBytes(4 + maskOffset)
+	if err != nil {
+		return err
+	}
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, uint16(4))
+	}
+	binary.BigEndian.PutUint16(bytes[maskOffset:], omci.AttributeMask)
+	binary.BigEndian.PutUint16(bytes[maskOffset+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)
+}
+
+// LayerType returns LayerTypeGetNextResponse
+func (omci *GetNextResponse) LayerType() gopacket.LayerType {
+	return LayerTypeGetNextResponse
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *GetNextResponse) CanDecode() gopacket.LayerClass {
+	return LayerTypeGetNextResponse
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *GetNextResponse) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		//start here
+		hdrSize = 6 + 3
+	} else {
+		hdrSize = 4 + 3
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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")
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	omci.Result = me.Results(data[4+offset])
+	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[4+offset+1:])
+
+	// Attribute decode
+	omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask, data[4+offset+3:], 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)
+}
+
+func decodeGetNextResponseExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &GetNextResponse{}
+	omci.MsgLayerType = LayerTypeGetNextResponse
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Get Next Message Type Response
+func (omci *GetNextResponse) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	bytes, err := b.AppendBytes(offset + 3)
+	if err != nil {
+		return err
+	}
+	bytes[offset] = 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[offset+1:], 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
+		if omci.Extended {
+			bytesAvailable := MaxExtendedLength - 13 - 4
+			attributeBuffer := gopacket.NewSerializeBuffer()
+			err, _ = meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask,
+				attributeBuffer, byte(GetNextResponseType), bytesAvailable, false)
+			if err != nil {
+				return err
+			}
+			binary.BigEndian.PutUint16(bytes, uint16(len(attributeBuffer.Bytes())+3))
+			var newSpace []byte
+
+			newSpace, err = b.AppendBytes(len(attributeBuffer.Bytes()))
+			if err != nil {
+				return err
+			}
+			copy(newSpace, attributeBuffer.Bytes())
+		} else {
+			bytesAvailable := MaxBaselineLength - 11 - 8
+
+			err, _ = meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask, b,
+				byte(GetNextResponseType), bytesAvailable, false)
+			if err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
diff --git a/getnext_test.go b/getnext_test.go
new file mode 100644
index 0000000..f205ab0
--- /dev/null
+++ b/getnext_test.go
@@ -0,0 +1,390 @@
+/*
+ * 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_test
+
+import (
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/stretchr/testify/assert"
+	"strings"
+	"testing"
+)
+
+func TestGetNextRequestDecode(t *testing.T) {
+	goodMessage := "285e5a0a00ab0202040000010000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeGetNextRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x285e), omciMsg.TransactionID)
+	assert.Equal(t, GetNextRequestType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeGetNextRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*GetNextRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeGetNextRequest, request.LayerType())
+	assert.Equal(t, LayerTypeGetNextRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, me.ExtendedVlanTaggingOperationConfigurationDataClassID, request.EntityClass)
+	assert.Equal(t, uint16(0x0202), request.EntityInstance)
+	assert.Equal(t, uint16(0x0400), request.AttributeMask)
+	assert.Equal(t, uint16(1), request.SequenceNumber)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestGetNextRequestDecodeExtended(t *testing.T) {
+	goodMessage := "285e5a0b00ab0202000404000001"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeGetNextRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x285e), omciMsg.TransactionID)
+	assert.Equal(t, GetNextRequestType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(4), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeGetNextRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*GetNextRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeGetNextRequest, request.LayerType())
+	assert.Equal(t, LayerTypeGetNextRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, me.ExtendedVlanTaggingOperationConfigurationDataClassID, request.EntityClass)
+	assert.Equal(t, uint16(0x0202), request.EntityInstance)
+	assert.Equal(t, uint16(0x0400), request.AttributeMask)
+	assert.Equal(t, uint16(1), request.SequenceNumber)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestGetNextRequestSerialize(t *testing.T) {
+	goodMessage := "285e5a0a00ab0202040000010000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x285e,
+		MessageType:   GetNextRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &GetNextRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x0202),
+		},
+		AttributeMask:  uint16(0x0400),
+		SequenceNumber: uint16(1),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestGetNextRequestZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   GetNextRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &GetNextRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x0202),
+		},
+		AttributeMask:  uint16(0x0400),
+		SequenceNumber: uint16(1),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestGetNextRequestSerializeExtended(t *testing.T) {
+	goodMessage := "285e5a0b00ab0202000404000001"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x285e,
+		MessageType:      GetNextRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &GetNextRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x0202),
+			Extended:       true,
+		},
+		AttributeMask:  uint16(0x0400),
+		SequenceNumber: uint16(1),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestGetNextResponseDecode(t *testing.T) {
+	goodMessage := "285e3a0a00ab0202000400080334000000000000000000000000000000000000000000000000000000000028"
+
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeGetNextResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x285e), omciMsg.TransactionID)
+	assert.Equal(t, GetNextResponseType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeGetNextResponse)
+	assert.NotNil(t, msgLayer)
+
+	vlanOpTable := []byte{0x08, 0x03, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+
+	response, ok2 := msgLayer.(*GetNextResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeGetNextResponse, response.LayerType())
+	assert.Equal(t, LayerTypeGetNextResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, me.ExtendedVlanTaggingOperationConfigurationDataClassID, response.EntityClass)
+	assert.Equal(t, uint16(0x0202), response.EntityInstance)
+	assert.Equal(t, me.Success, response.Result)
+	assert.Equal(t, uint16(0x0400), response.AttributeMask)
+
+	// For GetNextResponse frames, caller is responsible for trimming last packet to remaining
+	// size
+	expectedOctets := 16
+	value := response.Attributes["ReceivedFrameVlanTaggingOperationTable"]
+	assert.Equal(t, value.([]byte)[:expectedOctets], vlanOpTable)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestGetNextResponseDecodeExtended(t *testing.T) {
+	goodMessage := "285e3a0b00ab0202001300040008033400000000000000000000000000"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeGetNextResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x285e), omciMsg.TransactionID)
+	assert.Equal(t, GetNextResponseType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(19), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeGetNextResponse)
+	assert.NotNil(t, msgLayer)
+
+	vlanOpTable := []byte{0x08, 0x03, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+
+	response, ok2 := msgLayer.(*GetNextResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeGetNextResponse, response.LayerType())
+	assert.Equal(t, LayerTypeGetNextResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, me.ExtendedVlanTaggingOperationConfigurationDataClassID, response.EntityClass)
+	assert.Equal(t, uint16(0x0202), response.EntityInstance)
+	assert.Equal(t, me.Success, response.Result)
+	assert.Equal(t, uint16(0x0400), response.AttributeMask)
+
+	// For GetNextResponse frames, caller is responsible for trimming last packet to remaining
+	// size
+	expectedOctets := 16
+	value := response.Attributes["ReceivedFrameVlanTaggingOperationTable"]
+	assert.Equal(t, value.([]byte)[:expectedOctets], vlanOpTable)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestGetNextResponseSerialize(t *testing.T) {
+	goodMessage := "285e3a0a00ab0202000400080334000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x285e,
+		MessageType:   GetNextResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	vlanOpTable := []byte{0x08, 0x03, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+
+	request := &GetNextResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x0202),
+		},
+		Result:        me.Success,
+		AttributeMask: uint16(0x0400),
+		Attributes:    me.AttributeValueMap{"ReceivedFrameVlanTaggingOperationTable": vlanOpTable},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestGetNextResponseZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   GetNextResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	vlanOpTable := []byte{0x08, 0x03, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+
+	request := &GetNextResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x0202),
+		},
+		Result:        me.Success,
+		AttributeMask: uint16(0x0400),
+		Attributes:    me.AttributeValueMap{"ReceivedFrameVlanTaggingOperationTable": vlanOpTable},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestGetNextResponseSerializeExtended(t *testing.T) {
+	goodMessage := "285e3a0b00ab0202001300040008033400000000000000000000000000"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x285e,
+		MessageType:      GetNextResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	vlanOpTable := []byte{0x08, 0x03, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+
+	request := &GetNextResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x0202),
+			Extended:       true,
+		},
+		Result:        me.Success,
+		AttributeMask: uint16(0x0400),
+		Attributes:    me.AttributeValueMap{"ReceivedFrameVlanTaggingOperationTable": vlanOpTable},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
diff --git a/layers.go b/layers.go
index 1e0b686..cc9aa88 100644
--- a/layers.go
+++ b/layers.go
@@ -26,7 +26,6 @@
 var nextLayerMapping map[MessageType]gopacket.LayerType
 
 var (
-	// Baseline Message Types
 	LayerTypeCreateRequest                gopacket.LayerType
 	LayerTypeDeleteRequest                gopacket.LayerType
 	LayerTypeSetRequest                   gopacket.LayerType
@@ -49,13 +48,28 @@
 	LayerTypeGetCurrentDataRequest        gopacket.LayerType
 	LayerTypeSetTableRequest              gopacket.LayerType
 
-	// Extended Request Message Types
-	LayerTypeGetRequestExtended                 gopacket.LayerType
-	LayerTypeDownloadSectionRequestExtended     gopacket.LayerType
-	LayerTypeDownloadSectionLastRequestExtended gopacket.LayerType
+	LayerTypeCreateRequestExtended                gopacket.LayerType
+	LayerTypeDeleteRequestExtended                gopacket.LayerType
+	LayerTypeSetRequestExtended                   gopacket.LayerType
+	LayerTypeMibUploadRequestExtended             gopacket.LayerType
+	LayerTypeMibUploadNextRequestExtended         gopacket.LayerType
+	LayerTypeMibResetRequestExtended              gopacket.LayerType
+	LayerTypeGetRequestExtended                   gopacket.LayerType
+	LayerTypeGetNextRequestExtended               gopacket.LayerType
+	LayerTypeStartSoftwareDownloadRequestExtended gopacket.LayerType
+	LayerTypeDownloadSectionRequestExtended       gopacket.LayerType
+	LayerTypeDownloadSectionLastRequestExtended   gopacket.LayerType
+	LayerTypeEndSoftwareDownloadRequestExtended   gopacket.LayerType
+	LayerTypeActivateSoftwareRequestExtended      gopacket.LayerType
+	LayerTypeCommitSoftwareRequestExtended        gopacket.LayerType
+	LayerTypeSynchronizeTimeRequestExtended       gopacket.LayerType
+	LayerTypeRebootRequestExtended                gopacket.LayerType
+	LayerTypeGetCurrentDataRequestExtended        gopacket.LayerType
+	LayerTypeSetTableRequestExtended              gopacket.LayerType
+	LayerTypeGetAllAlarmsRequestExtended          gopacket.LayerType
+	LayerTypeGetAllAlarmsNextRequestExtended      gopacket.LayerType
 )
 var (
-	// Baseline Message Types
 	LayerTypeCreateResponse                gopacket.LayerType
 	LayerTypeDeleteResponse                gopacket.LayerType
 	LayerTypeSetResponse                   gopacket.LayerType
@@ -80,12 +94,28 @@
 	LayerTypeGetCurrentDataResponse        gopacket.LayerType
 	LayerTypeSetTableResponse              gopacket.LayerType
 
-	// Extended Response/Notification Message Types
-	LayerTypeGetResponseExtended             gopacket.LayerType
-	LayerTypeDownloadSectionResponseExtended gopacket.LayerType
-	LayerTypeAlarmNotificationExtended       gopacket.LayerType
-	LayerTypeAttributeValueChangeExtended    gopacket.LayerType
-	LayerTypeTestResultExtended              gopacket.LayerType
+	LayerTypeCreateResponseExtended                gopacket.LayerType
+	LayerTypeDeleteResponseExtended                gopacket.LayerType
+	LayerTypeSetResponseExtended                   gopacket.LayerType
+	LayerTypeMibUploadResponseExtended             gopacket.LayerType
+	LayerTypeMibUploadNextResponseExtended         gopacket.LayerType
+	LayerTypeMibResetResponseExtended              gopacket.LayerType
+	LayerTypeGetResponseExtended                   gopacket.LayerType
+	LayerTypeGetNextResponseExtended               gopacket.LayerType
+	LayerTypeStartSoftwareDownloadResponseExtended gopacket.LayerType
+	LayerTypeDownloadSectionResponseExtended       gopacket.LayerType
+	LayerTypeEndSoftwareDownloadResponseExtended   gopacket.LayerType
+	LayerTypeActivateSoftwareResponseExtended      gopacket.LayerType
+	LayerTypeCommitSoftwareResponseExtended        gopacket.LayerType
+	LayerTypeAlarmNotificationExtended             gopacket.LayerType
+	LayerTypeAttributeValueChangeExtended          gopacket.LayerType
+	LayerTypeTestResultExtended                    gopacket.LayerType
+	LayerTypeSynchronizeTimeResponseExtended       gopacket.LayerType
+	LayerTypeRebootResponseExtended                gopacket.LayerType
+	LayerTypeGetCurrentDataResponseExtended        gopacket.LayerType
+	LayerTypeSetTableResponseExtended              gopacket.LayerType
+	LayerTypeGetAllAlarmsResponseExtended          gopacket.LayerType
+	LayerTypeGetAllAlarmsNextResponseExtended      gopacket.LayerType
 )
 
 func mkReqLayer(mt me.MsgType, mts string, decode gopacket.DecodeFunc) gopacket.LayerType {
@@ -105,65 +135,100 @@
 
 func init() {
 	// Create layers for message_type & action
-	LayerTypeCreateRequest = mkReqLayer(me.Create, "CreateRequest", gopacket.DecodeFunc(decodeCreateRequest))
-	LayerTypeDeleteRequest = mkReqLayer(me.Delete, "DeleteRequest", gopacket.DecodeFunc(decodeDeleteRequest))
-	LayerTypeSetRequest = mkReqLayer(me.Set, "SetRequest", gopacket.DecodeFunc(decodeSetRequest))
-	LayerTypeGetRequest = mkReqLayer(me.Get, "GetRequest", gopacket.DecodeFunc(decodeGetRequest))
-	LayerTypeGetAllAlarmsRequest = mkReqLayer(me.GetAllAlarms, "GetAllAlarmsRequest", gopacket.DecodeFunc(decodeGetAllAlarmsRequest))
-	LayerTypeGetAllAlarmsNextRequest = mkReqLayer(me.GetAllAlarmsNext, "GetAllAlarmsNextRequest", gopacket.DecodeFunc(decodeGetAllAlarmsNextRequest))
-	LayerTypeMibUploadRequest = mkReqLayer(me.MibUpload, "MibUploadRequest", gopacket.DecodeFunc(decodeMibUploadRequest))
-	LayerTypeMibUploadNextRequest = mkReqLayer(me.MibUploadNext, "MibUploadNextRequest", gopacket.DecodeFunc(decodeMibUploadNextRequest))
-	LayerTypeMibResetRequest = mkReqLayer(me.MibReset, "MibResetRequest", gopacket.DecodeFunc(decodeMibResetRequest))
-	LayerTypeTestRequest = mkReqLayer(me.Test, "TestRequest", gopacket.DecodeFunc(decodeTestRequest))
-	LayerTypeStartSoftwareDownloadRequest = mkReqLayer(me.StartSoftwareDownload, "StartSoftwareDownloadRequest", gopacket.DecodeFunc(decodeStartSoftwareDownloadRequest))
+	LayerTypeCreateRequest = mkReqLayer(me.Create, "CreateRequest", decodeCreateRequest)
+	LayerTypeDeleteRequest = mkReqLayer(me.Delete, "DeleteRequest", decodeDeleteRequest)
+	LayerTypeSetRequest = mkReqLayer(me.Set, "SetRequest", decodeSetRequest)
+	LayerTypeGetRequest = mkReqLayer(me.Get, "GetRequest", decodeGetRequest)
+	LayerTypeGetAllAlarmsRequest = mkReqLayer(me.GetAllAlarms, "GetAllAlarmsRequest", decodeGetAllAlarmsRequest)
+	LayerTypeGetAllAlarmsNextRequest = mkReqLayer(me.GetAllAlarmsNext, "GetAllAlarmsNextRequest", decodeGetAllAlarmsNextRequest)
+	LayerTypeMibUploadRequest = mkReqLayer(me.MibUpload, "MibUploadRequest", decodeMibUploadRequest)
+	LayerTypeMibUploadNextRequest = mkReqLayer(me.MibUploadNext, "MibUploadNextRequest", decodeMibUploadNextRequest)
+	LayerTypeMibResetRequest = mkReqLayer(me.MibReset, "MibResetRequest", decodeMibResetRequest)
+	LayerTypeTestRequest = mkReqLayer(me.Test, "TestRequest", decodeTestRequest)
+	LayerTypeStartSoftwareDownloadRequest = mkReqLayer(me.StartSoftwareDownload, "StartSoftwareDownloadRequest", decodeStartSoftwareDownloadRequest)
 
 	// For Download section, AR=0 if not response expected, AR=1 if response expected (last section of a window)
-	LayerTypeDownloadSectionRequest = mkLayer(me.DownloadSection, "DownloadSectionRequest", gopacket.DecodeFunc(decodeDownloadSectionRequest))
-	LayerTypeDownloadSectionLastRequest = mkReqLayer(me.DownloadSection, "DownloadLastSectionRequest", gopacket.DecodeFunc(decodeDownloadSectionRequest))
-	LayerTypeEndSoftwareDownloadRequest = mkReqLayer(me.EndSoftwareDownload, "EndSoftwareDownloadRequest", gopacket.DecodeFunc(decodeEndSoftwareDownloadRequest))
-	LayerTypeActivateSoftwareRequest = mkReqLayer(me.ActivateSoftware, "ActivateSoftwareRequest", gopacket.DecodeFunc(decodeActivateSoftwareRequest))
-	LayerTypeCommitSoftwareRequest = mkReqLayer(me.CommitSoftware, "CommitSoftwareRequest", gopacket.DecodeFunc(decodeCommitSoftwareRequest))
-	LayerTypeSynchronizeTimeRequest = mkReqLayer(me.SynchronizeTime, "SynchronizeTimeRequest", gopacket.DecodeFunc(decodeSynchronizeTimeRequest))
-	LayerTypeRebootRequest = mkReqLayer(me.Reboot, "RebootRequest", gopacket.DecodeFunc(decodeRebootRequest))
-	LayerTypeGetNextRequest = mkReqLayer(me.GetNext, "GetNextRequest", gopacket.DecodeFunc(decodeGetNextRequest))
-	LayerTypeGetCurrentDataRequest = mkReqLayer(me.GetCurrentData, "GetCurrentDataRequest", gopacket.DecodeFunc(decodeGetCurrentDataRequest))
-	LayerTypeSetTableRequest = mkReqLayer(me.SetTable, "SetTableRequest", gopacket.DecodeFunc(decodeSetTableRequest))
+	LayerTypeDownloadSectionRequest = mkLayer(me.DownloadSection, "DownloadSectionRequest", decodeDownloadSectionRequest)
+	LayerTypeDownloadSectionLastRequest = mkReqLayer(me.DownloadSection, "DownloadLastSectionRequest", decodeDownloadSectionRequest)
+	LayerTypeEndSoftwareDownloadRequest = mkReqLayer(me.EndSoftwareDownload, "EndSoftwareDownloadRequest", decodeEndSoftwareDownloadRequest)
+	LayerTypeActivateSoftwareRequest = mkReqLayer(me.ActivateSoftware, "ActivateSoftwareRequest", decodeActivateSoftwareRequest)
+	LayerTypeCommitSoftwareRequest = mkReqLayer(me.CommitSoftware, "CommitSoftwareRequest", decodeCommitSoftwareRequest)
+	LayerTypeSynchronizeTimeRequest = mkReqLayer(me.SynchronizeTime, "SynchronizeTimeRequest", decodeSynchronizeTimeRequest)
+	LayerTypeRebootRequest = mkReqLayer(me.Reboot, "RebootRequest", decodeRebootRequest)
+	LayerTypeGetNextRequest = mkReqLayer(me.GetNext, "GetNextRequest", decodeGetNextRequest)
+	LayerTypeGetCurrentDataRequest = mkReqLayer(me.GetCurrentData, "GetCurrentDataRequest", decodeGetCurrentDataRequest)
+	LayerTypeSetTableRequest = mkReqLayer(me.SetTable, "SetTableRequest", decodeSetTableRequest)
 
-	LayerTypeCreateResponse = mkRespLayer(me.Create, "CreateResponse", gopacket.DecodeFunc(decodeCreateResponse))
-	LayerTypeDeleteResponse = mkRespLayer(me.Delete, "DeleteResponse", gopacket.DecodeFunc(decodeDeleteResponse))
-	LayerTypeSetResponse = mkRespLayer(me.Set, "SetResponse", gopacket.DecodeFunc(decodeSetResponse))
-	LayerTypeGetResponse = mkRespLayer(me.Get, "GetResponse", gopacket.DecodeFunc(decodeGetResponse))
-	LayerTypeGetAllAlarmsResponse = mkRespLayer(me.GetAllAlarms, "GetAllAlarmsResponse", gopacket.DecodeFunc(decodeGetAllAlarmsResponse))
-	LayerTypeGetAllAlarmsNextResponse = mkRespLayer(me.GetAllAlarmsNext, "GetAllAlarmsNextResponse", gopacket.DecodeFunc(decodeGetAllAlarmsNextResponse))
-	LayerTypeMibUploadResponse = mkRespLayer(me.MibUpload, "MibUploadResponse", gopacket.DecodeFunc(decodeMibUploadResponse))
-	LayerTypeMibUploadNextResponse = mkRespLayer(me.MibUploadNext, "MibUploadNextResponse", gopacket.DecodeFunc(decodeMibUploadNextResponse))
-	LayerTypeMibResetResponse = mkRespLayer(me.MibReset, "MibResetResponse", gopacket.DecodeFunc(decodeMibResetResponse))
-	LayerTypeAlarmNotification = mkLayer(me.AlarmNotification, "AlarmNotification", gopacket.DecodeFunc(decodeAlarmNotification))
-	LayerTypeAttributeValueChange = mkLayer(me.AttributeValueChange, "AttributeValueChange", gopacket.DecodeFunc(decodeAttributeValueChange))
-	LayerTypeTestResponse = mkRespLayer(me.Test, "TestResponse", gopacket.DecodeFunc(decodeTestResponse))
-	LayerTypeStartSoftwareDownloadResponse = mkRespLayer(me.StartSoftwareDownload, "StartSoftwareDownloadResponse", gopacket.DecodeFunc(decodeStartSoftwareDownloadResponse))
-	LayerTypeDownloadSectionResponse = mkRespLayer(me.DownloadSection, "DownloadSectionResponse", gopacket.DecodeFunc(decodeDownloadSectionResponse))
-	LayerTypeEndSoftwareDownloadResponse = mkRespLayer(me.EndSoftwareDownload, "EndSoftwareDownloadResponse", gopacket.DecodeFunc(decodeEndSoftwareDownloadResponse))
-	LayerTypeActivateSoftwareResponse = mkRespLayer(me.ActivateSoftware, "ActivateSoftwareResponse", gopacket.DecodeFunc(decodeActivateSoftwareResponse))
-	LayerTypeCommitSoftwareResponse = mkRespLayer(me.CommitSoftware, "CommitSoftwareResponse", gopacket.DecodeFunc(decodeCommitSoftwareResponse))
-	LayerTypeSynchronizeTimeResponse = mkRespLayer(me.SynchronizeTime, "SynchronizeTimeResponse", gopacket.DecodeFunc(decodeSynchronizeTimeResponse))
-	LayerTypeRebootResponse = mkRespLayer(me.Reboot, "RebootResponse", gopacket.DecodeFunc(decodeRebootResponse))
-	LayerTypeGetNextResponse = mkRespLayer(me.GetNext, "GetNextResponse", gopacket.DecodeFunc(decodeGetNextResponse))
-	LayerTypeTestResult = mkRespLayer(me.TestResult, "TestResult", gopacket.DecodeFunc(decodeTestResult))
-	LayerTypeGetCurrentDataResponse = mkRespLayer(me.GetCurrentData, "GetCurrentDataResponse", gopacket.DecodeFunc(decodeGetCurrentDataResponse))
-	LayerTypeSetTableResponse = mkRespLayer(me.SetTable, "SetTableResponse", gopacket.DecodeFunc(decodeSetTableResponse))
+	LayerTypeCreateResponse = mkRespLayer(me.Create, "CreateResponse", decodeCreateResponse)
+	LayerTypeDeleteResponse = mkRespLayer(me.Delete, "DeleteResponse", decodeDeleteResponse)
+	LayerTypeSetResponse = mkRespLayer(me.Set, "SetResponse", decodeSetResponse)
+	LayerTypeGetResponse = mkRespLayer(me.Get, "GetResponse", decodeGetResponse)
+	LayerTypeGetAllAlarmsResponse = mkRespLayer(me.GetAllAlarms, "GetAllAlarmsResponse", decodeGetAllAlarmsResponse)
+	LayerTypeGetAllAlarmsNextResponse = mkRespLayer(me.GetAllAlarmsNext, "GetAllAlarmsNextResponse", decodeGetAllAlarmsNextResponse)
+	LayerTypeMibUploadResponse = mkRespLayer(me.MibUpload, "MibUploadResponse", decodeMibUploadResponse)
+	LayerTypeMibUploadNextResponse = mkRespLayer(me.MibUploadNext, "MibUploadNextResponse", decodeMibUploadNextResponse)
+	LayerTypeMibResetResponse = mkRespLayer(me.MibReset, "MibResetResponse", decodeMibResetResponse)
+	LayerTypeAlarmNotification = mkLayer(me.AlarmNotification, "AlarmNotification", decodeAlarmNotification)
+	LayerTypeAttributeValueChange = mkLayer(me.AttributeValueChange, "AttributeValueChange", decodeAttributeValueChange)
+	LayerTypeTestResponse = mkRespLayer(me.Test, "TestResponse", decodeTestResponse)
+	LayerTypeStartSoftwareDownloadResponse = mkRespLayer(me.StartSoftwareDownload, "StartSoftwareDownloadResponse", decodeStartSoftwareDownloadResponse)
+	LayerTypeDownloadSectionResponse = mkRespLayer(me.DownloadSection, "DownloadSectionResponse", decodeDownloadSectionResponse)
+	LayerTypeEndSoftwareDownloadResponse = mkRespLayer(me.EndSoftwareDownload, "EndSoftwareDownloadResponse", decodeEndSoftwareDownloadResponse)
+	LayerTypeActivateSoftwareResponse = mkRespLayer(me.ActivateSoftware, "ActivateSoftwareResponse", decodeActivateSoftwareResponse)
+	LayerTypeCommitSoftwareResponse = mkRespLayer(me.CommitSoftware, "CommitSoftwareResponse", decodeCommitSoftwareResponse)
+	LayerTypeSynchronizeTimeResponse = mkRespLayer(me.SynchronizeTime, "SynchronizeTimeResponse", decodeSynchronizeTimeResponse)
+	LayerTypeRebootResponse = mkRespLayer(me.Reboot, "RebootResponse", decodeRebootResponse)
+	LayerTypeGetNextResponse = mkRespLayer(me.GetNext, "GetNextResponse", decodeGetNextResponse)
+	LayerTypeTestResult = mkRespLayer(me.TestResult, "TestResult", decodeTestResult)
+	LayerTypeGetCurrentDataResponse = mkRespLayer(me.GetCurrentData, "GetCurrentDataResponse", decodeGetCurrentDataResponse)
+	LayerTypeSetTableResponse = mkRespLayer(me.SetTable, "SetTableResponse", decodeSetTableResponse)
 
 	// Extended message set support
 
-	LayerTypeGetRequestExtended = mkReqLayer(me.Get|me.ExtendedOffset, "GetRequest-Ext", gopacket.DecodeFunc(decodeGetRequestExtended))
-	LayerTypeGetResponseExtended = mkRespLayer(me.Get|me.ExtendedOffset, "GetResponse-Ext", gopacket.DecodeFunc(decodeGetResponseExtended))
-	LayerTypeDownloadSectionRequestExtended = mkLayer(me.DownloadSection|me.ExtendedOffset, "DownloadSectionRequest-Ext", gopacket.DecodeFunc(decodeDownloadSectionRequestExtended))
-	LayerTypeDownloadSectionLastRequestExtended = mkReqLayer(me.DownloadSection|me.ExtendedOffset, "DownloadLastSectionRequest-Ext", gopacket.DecodeFunc(decodeDownloadSectionRequestExtended))
-	LayerTypeDownloadSectionResponseExtended = mkRespLayer(me.DownloadSection|me.ExtendedOffset, "DownloadSectionResponse-Ext", gopacket.DecodeFunc(decodeDownloadSectionResponseExtended))
+	LayerTypeCreateRequestExtended = mkReqLayer(me.Create|me.ExtendedOffset, "CreateRequest-Ext", decodeCreateRequestExtended)
+	LayerTypeDeleteRequestExtended = mkReqLayer(me.Delete|me.ExtendedOffset, "DeleteRequest-Ext", decodeDeleteRequestExtended)
+	LayerTypeSetRequestExtended = mkReqLayer(me.Set|me.ExtendedOffset, "SetRequest-Ext", decodeSetRequestExtended)
+	LayerTypeGetRequestExtended = mkReqLayer(me.Get|me.ExtendedOffset, "GetRequest-Ext", decodeGetRequestExtended)
+	LayerTypeGetNextRequestExtended = mkReqLayer(me.GetNext|me.ExtendedOffset, "GetNextRequest-Ext", decodeGetNextRequestExtended)
+	LayerTypeMibUploadRequestExtended = mkReqLayer(me.MibUpload|me.ExtendedOffset, "MibUploadRequest-Ext", decodeMibUploadRequestExtended)
+	LayerTypeMibUploadNextRequestExtended = mkReqLayer(me.MibUploadNext|me.ExtendedOffset, "MibUploadNextRequest-Ext", decodeMibUploadNextRequestExtended)
+	LayerTypeMibResetRequestExtended = mkReqLayer(me.MibReset|me.ExtendedOffset, "MibResetRequest-Ext", decodeMibResetRequestExtended)
+	LayerTypeStartSoftwareDownloadRequestExtended = mkReqLayer(me.StartSoftwareDownload|me.ExtendedOffset, "StartSoftwareDownloadRequest-Ext", decodeStartSoftwareDownloadRequestExtended)
+	LayerTypeDownloadSectionRequestExtended = mkLayer(me.DownloadSection|me.ExtendedOffset, "DownloadSectionRequest-Ext", decodeDownloadSectionRequestExtended)
+	LayerTypeDownloadSectionLastRequestExtended = mkReqLayer(me.DownloadSection|me.ExtendedOffset, "DownloadLastSectionRequest-Ext", decodeDownloadSectionRequestExtended)
+	LayerTypeEndSoftwareDownloadRequestExtended = mkReqLayer(me.EndSoftwareDownload|me.ExtendedOffset, "EndSoftwareDownloadRequest-Ext", decodeEndSoftwareDownloadRequestExtended)
+	LayerTypeActivateSoftwareRequestExtended = mkReqLayer(me.ActivateSoftware|me.ExtendedOffset, "ActivateSoftwareRequest-Ext", decodeActivateSoftwareRequestExtended)
+	LayerTypeCommitSoftwareRequestExtended = mkReqLayer(me.CommitSoftware|me.ExtendedOffset, "CommitSoftwareRequest-Ext", decodeCommitSoftwareRequestExtended)
+	LayerTypeSynchronizeTimeRequestExtended = mkReqLayer(me.SynchronizeTime|me.ExtendedOffset, "SynchronizeTimeRequest-Ext", decodeSynchronizeTimeRequestExtended)
+	LayerTypeRebootRequestExtended = mkReqLayer(me.Reboot|me.ExtendedOffset, "RebootRequest-Ext", decodeRebootRequestExtended)
+	LayerTypeGetCurrentDataRequestExtended = mkReqLayer(me.GetCurrentData|me.ExtendedOffset, "GetCurrentDataRequest-Ext", decodeGetCurrentDataRequestExtended)
+	LayerTypeSetTableRequestExtended = mkReqLayer(me.SetTable|me.ExtendedOffset, "SetTableRequest-Ext", decodeSetTableRequestExtended)
+	LayerTypeGetAllAlarmsRequestExtended = mkReqLayer(me.GetAllAlarms|me.ExtendedOffset, "GetAllAlarmsRequest-Ext", decodeGetAllAlarmsRequestExtended)
+	LayerTypeGetAllAlarmsNextRequestExtended = mkReqLayer(me.GetAllAlarmsNext|me.ExtendedOffset, "GetAllAlarmsNextRequest-Ext", decodeGetAllAlarmsNextRequestExtended)
 
-	LayerTypeAlarmNotificationExtended = mkLayer(me.AlarmNotification|me.ExtendedOffset, "AlarmNotification-Ext", gopacket.DecodeFunc(decodeAlarmNotificationExtended))
-	LayerTypeAttributeValueChangeExtended = mkLayer(me.AttributeValueChange|me.ExtendedOffset, "AttributeValueChange-Ext", gopacket.DecodeFunc(decodeAttributeValueChangeExtended))
-	LayerTypeTestResultExtended = mkLayer(me.TestResult|me.ExtendedOffset, "TestResult-Ext", gopacket.DecodeFunc(decodeTestResultExtended))
+	LayerTypeCreateResponseExtended = mkRespLayer(me.Create|me.ExtendedOffset, "CreateResponse-Ext", decodeCreateResponseExtended)
+	LayerTypeDeleteResponseExtended = mkRespLayer(me.Delete|me.ExtendedOffset, "DeleteResponse-Ext", decodeDeleteResponseExtended)
+	LayerTypeSetResponseExtended = mkRespLayer(me.Set|me.ExtendedOffset, "SetResponse-Ext", decodeSetResponseExtended)
+	LayerTypeGetResponseExtended = mkRespLayer(me.Get|me.ExtendedOffset, "GetResponse-Ext", decodeGetResponseExtended)
+	LayerTypeGetNextResponseExtended = mkRespLayer(me.GetNext|me.ExtendedOffset, "GetNextResponse-Ext", decodeGetNextResponseExtended)
+	LayerTypeMibUploadResponseExtended = mkRespLayer(me.MibUpload|me.ExtendedOffset, "MibUploadResponse-Ext", decodeMibUploadResponseExtended)
+	LayerTypeMibUploadNextResponseExtended = mkRespLayer(me.MibUploadNext|me.ExtendedOffset, "MibUploadNextResponse-Ext", decodeMibUploadNextResponseExtended)
+	LayerTypeMibResetResponseExtended = mkRespLayer(me.MibReset|me.ExtendedOffset, "MibResetResponse-Ext", decodeMibResetResponseExtended)
+	LayerTypeStartSoftwareDownloadResponseExtended = mkRespLayer(me.StartSoftwareDownload|me.ExtendedOffset, "StartSoftwareDownloadResponse-Ext", decodeStartSoftwareDownloadResponseExtended)
+	LayerTypeDownloadSectionResponseExtended = mkRespLayer(me.DownloadSection|me.ExtendedOffset, "DownloadSectionResponse-Ext", decodeDownloadSectionResponseExtended)
+	LayerTypeEndSoftwareDownloadResponseExtended = mkRespLayer(me.EndSoftwareDownload|me.ExtendedOffset, "EndSoftwareDownloadResponse-Ext", decodeEndSoftwareDownloadResponseExtended)
+	LayerTypeActivateSoftwareResponseExtended = mkRespLayer(me.ActivateSoftware|me.ExtendedOffset, "ActivateSoftwareResponse-Ext", decodeActivateSoftwareResponseExtended)
+	LayerTypeCommitSoftwareResponseExtended = mkRespLayer(me.CommitSoftware|me.ExtendedOffset, "CommitSoftwareResponse-Ext", decodeCommitSoftwareResponseExtended)
+	LayerTypeSynchronizeTimeResponseExtended = mkRespLayer(me.SynchronizeTime|me.ExtendedOffset, "SynchronizeTimeResponse-Ext", decodeSynchronizeTimeResponseExtended)
+	LayerTypeRebootResponseExtended = mkRespLayer(me.Reboot|me.ExtendedOffset, "RebootResponse-Ext", decodeRebootResponseExtended)
+	LayerTypeGetCurrentDataResponseExtended = mkRespLayer(me.GetCurrentData|me.ExtendedOffset, "GetCurrentDataResponse-Ext", decodeGetCurrentDataResponseExtended)
+	LayerTypeSetTableResponseExtended = mkRespLayer(me.SetTable|me.ExtendedOffset, "SetTableResponse-Ext", decodeSetTableResponseExtended)
+	LayerTypeGetAllAlarmsResponseExtended = mkRespLayer(me.GetAllAlarms|me.ExtendedOffset, "GetAllAlarmsResponse-Ext", decodeGetAllAlarmsResponseExtended)
+	LayerTypeGetAllAlarmsNextResponseExtended = mkRespLayer(me.GetAllAlarmsNext|me.ExtendedOffset, "GetAllAlarmsNextResponse-Ext", decodeGetAllAlarmsNextResponseExtended)
+
+	LayerTypeAlarmNotificationExtended = mkLayer(me.AlarmNotification|me.ExtendedOffset, "AlarmNotification-Ext", decodeAlarmNotificationExtended)
+	LayerTypeAttributeValueChangeExtended = mkLayer(me.AttributeValueChange|me.ExtendedOffset, "AttributeValueChange-Ext", decodeAttributeValueChangeExtended)
+	LayerTypeTestResultExtended = mkLayer(me.TestResult|me.ExtendedOffset, "TestResult-Ext", decodeTestResultExtended)
 
 	// Map message_type and action to layer
 	nextLayerMapping = make(map[MessageType]gopacket.LayerType)
@@ -180,7 +245,7 @@
 	nextLayerMapping[TestRequestType] = LayerTypeTestRequest
 	nextLayerMapping[StartSoftwareDownloadRequestType] = LayerTypeStartSoftwareDownloadRequest
 	nextLayerMapping[DownloadSectionRequestType] = LayerTypeDownloadSectionRequest
-	nextLayerMapping[DownloadSectionRequestWithResponseType] = LayerTypeDownloadSectionRequest
+	nextLayerMapping[DownloadSectionRequestWithResponseType] = LayerTypeDownloadSectionLastRequest
 	nextLayerMapping[EndSoftwareDownloadRequestType] = LayerTypeEndSoftwareDownloadRequest
 	nextLayerMapping[ActivateSoftwareRequestType] = LayerTypeActivateSoftwareRequest
 	nextLayerMapping[CommitSoftwareRequestType] = LayerTypeCommitSoftwareRequest
@@ -188,7 +253,6 @@
 	nextLayerMapping[RebootRequestType] = LayerTypeRebootRequest
 	nextLayerMapping[GetNextRequestType] = LayerTypeGetNextRequest
 	nextLayerMapping[GetCurrentDataRequestType] = LayerTypeGetCurrentDataRequest
-	nextLayerMapping[SetTableRequestType] = LayerTypeSetTableRequest
 
 	nextLayerMapping[CreateResponseType] = LayerTypeCreateResponse
 	nextLayerMapping[DeleteResponseType] = LayerTypeDeleteResponse
@@ -209,21 +273,64 @@
 	nextLayerMapping[RebootResponseType] = LayerTypeRebootResponse
 	nextLayerMapping[GetNextResponseType] = LayerTypeGetNextResponse
 	nextLayerMapping[GetCurrentDataResponseType] = LayerTypeGetCurrentDataResponse
-	nextLayerMapping[SetTableResponseType] = LayerTypeSetTableResponse
 
 	nextLayerMapping[AttributeValueChangeType] = LayerTypeAttributeValueChange
 	nextLayerMapping[AlarmNotificationType] = LayerTypeAlarmNotification
 	nextLayerMapping[TestResultType] = LayerTypeTestResult
 
+	nextLayerMapping[SetTableRequestType] = LayerTypeSetTableRequest
+	nextLayerMapping[SetTableResponseType] = LayerTypeSetTableResponse
+
 	// Extended message support
+	nextLayerMapping[CreateRequestType+ExtendedTypeDecodeOffset] = LayerTypeCreateRequestExtended
+	nextLayerMapping[CreateResponseType+ExtendedTypeDecodeOffset] = LayerTypeCreateResponseExtended
+	nextLayerMapping[DeleteResponseType+ExtendedTypeDecodeOffset] = LayerTypeDeleteResponseExtended
+	nextLayerMapping[DeleteRequestType+ExtendedTypeDecodeOffset] = LayerTypeDeleteRequestExtended
+	nextLayerMapping[SetRequestType+ExtendedTypeDecodeOffset] = LayerTypeSetRequestExtended
+	nextLayerMapping[SetResponseType+ExtendedTypeDecodeOffset] = LayerTypeSetResponseExtended
 	nextLayerMapping[GetRequestType+ExtendedTypeDecodeOffset] = LayerTypeGetRequestExtended
 	nextLayerMapping[GetResponseType+ExtendedTypeDecodeOffset] = LayerTypeGetResponseExtended
+	nextLayerMapping[GetNextRequestType+ExtendedTypeDecodeOffset] = LayerTypeGetNextRequestExtended
+	nextLayerMapping[GetNextResponseType+ExtendedTypeDecodeOffset] = LayerTypeGetNextResponseExtended
 
+	nextLayerMapping[MibUploadRequestType+ExtendedTypeDecodeOffset] = LayerTypeMibUploadRequestExtended
+	nextLayerMapping[MibUploadResponseType+ExtendedTypeDecodeOffset] = LayerTypeMibUploadResponseExtended
+	nextLayerMapping[MibUploadNextRequestType+ExtendedTypeDecodeOffset] = LayerTypeMibUploadNextRequestExtended
+	nextLayerMapping[MibUploadNextResponseType+ExtendedTypeDecodeOffset] = LayerTypeMibUploadNextResponseExtended
+
+	nextLayerMapping[MibResetRequestType+ExtendedTypeDecodeOffset] = LayerTypeMibResetRequestExtended
+	nextLayerMapping[MibResetResponseType+ExtendedTypeDecodeOffset] = LayerTypeMibResetResponseExtended
+	nextLayerMapping[SynchronizeTimeRequestType+ExtendedTypeDecodeOffset] = LayerTypeSynchronizeTimeRequestExtended
+	nextLayerMapping[SynchronizeTimeResponseType+ExtendedTypeDecodeOffset] = LayerTypeSynchronizeTimeResponseExtended
+	nextLayerMapping[RebootRequestType+ExtendedTypeDecodeOffset] = LayerTypeRebootRequestExtended
+	nextLayerMapping[RebootResponseType+ExtendedTypeDecodeOffset] = LayerTypeRebootResponseExtended
+	nextLayerMapping[GetCurrentDataRequestType+ExtendedTypeDecodeOffset] = LayerTypeGetCurrentDataRequestExtended
+	nextLayerMapping[GetCurrentDataResponseType+ExtendedTypeDecodeOffset] = LayerTypeGetCurrentDataResponseExtended
+
+	nextLayerMapping[SetTableRequestType+ExtendedTypeDecodeOffset] = LayerTypeSetTableRequestExtended
+	nextLayerMapping[SetTableResponseType+ExtendedTypeDecodeOffset] = LayerTypeSetTableResponseExtended
+
+	nextLayerMapping[GetAllAlarmsRequestType+ExtendedTypeDecodeOffset] = LayerTypeGetAllAlarmsRequestExtended
+	nextLayerMapping[GetAllAlarmsNextRequestType+ExtendedTypeDecodeOffset] = LayerTypeGetAllAlarmsNextRequestExtended
+	nextLayerMapping[GetAllAlarmsResponseType+ExtendedTypeDecodeOffset] = LayerTypeGetAllAlarmsResponseExtended
+	nextLayerMapping[GetAllAlarmsNextResponseType+ExtendedTypeDecodeOffset] = LayerTypeGetAllAlarmsNextResponseExtended
+
+	nextLayerMapping[StartSoftwareDownloadRequestType+ExtendedTypeDecodeOffset] = LayerTypeStartSoftwareDownloadRequestExtended
+	nextLayerMapping[StartSoftwareDownloadResponseType+ExtendedTypeDecodeOffset] = LayerTypeStartSoftwareDownloadResponseExtended
 	// For Download section, AR=0 if not response expected, AR=1 if response expected (last section of a window)
 	nextLayerMapping[DownloadSectionRequestType+ExtendedTypeDecodeOffset] = LayerTypeDownloadSectionRequestExtended
 	nextLayerMapping[DownloadSectionRequestWithResponseType+ExtendedTypeDecodeOffset] = LayerTypeDownloadSectionLastRequestExtended
 	nextLayerMapping[DownloadSectionResponseType+ExtendedTypeDecodeOffset] = LayerTypeDownloadSectionResponseExtended
 
+	nextLayerMapping[EndSoftwareDownloadRequestType+ExtendedTypeDecodeOffset] = LayerTypeEndSoftwareDownloadRequestExtended
+	nextLayerMapping[EndSoftwareDownloadResponseType+ExtendedTypeDecodeOffset] = LayerTypeEndSoftwareDownloadResponseExtended
+
+	nextLayerMapping[ActivateSoftwareRequestType+ExtendedTypeDecodeOffset] = LayerTypeActivateSoftwareRequestExtended
+	nextLayerMapping[ActivateSoftwareResponseType+ExtendedTypeDecodeOffset] = LayerTypeActivateSoftwareResponseExtended
+
+	nextLayerMapping[CommitSoftwareRequestType+ExtendedTypeDecodeOffset] = LayerTypeCommitSoftwareRequestExtended
+	nextLayerMapping[CommitSoftwareResponseType+ExtendedTypeDecodeOffset] = LayerTypeCommitSoftwareResponseExtended
+
 	nextLayerMapping[AlarmNotificationType+ExtendedTypeDecodeOffset] = LayerTypeAlarmNotificationExtended
 	nextLayerMapping[AttributeValueChangeType+ExtendedTypeDecodeOffset] = LayerTypeAttributeValueChangeExtended
 	nextLayerMapping[TestResultType+ExtendedTypeDecodeOffset] = LayerTypeTestResultExtended
diff --git a/mebase.go b/mebase.go
index 41f7a1f..2681078 100644
--- a/mebase.go
+++ b/mebase.go
@@ -67,7 +67,15 @@
 
 // DecodeFromBytes decodes the given bytes into this layer
 func (msg *MeBasePacket) DecodeFromBytes(data []byte, p gopacket.PacketBuilder, contentSize int) error {
-	// Note: Base OMCI frame already checked for frame with at least 10 octets
+	if len(data) < contentSize {
+		p.SetTruncated()
+		layerType := msg.LayerType().String()
+		if msg.Extended {
+			layerType += " (extended)"
+		}
+		return fmt.Errorf("frame header too small. %v header length %v, %v required",
+			layerType, len(data), contentSize)
+	}
 	msg.EntityClass = me.ClassID(binary.BigEndian.Uint16(data[0:]))
 	msg.EntityInstance = binary.BigEndian.Uint16(data[2:])
 	msg.BaseLayer = layers.BaseLayer{Contents: data[:contentSize], Payload: data[contentSize:]}
diff --git a/mebase_test.go b/mebase_test.go
index 3c0fe0e..41e8e7c 100644
--- a/mebase_test.go
+++ b/mebase_test.go
@@ -57,3 +57,102 @@
 	mock := simpleMock(t)
 	assert.Equal(t, mock.CanDecode(), mock.MsgLayerType)
 }
+
+func TestDecodesFrameNoTrailer(t *testing.T) {
+	// No baseline trailer.  Which is okay. Earlier library release depended on at
+	// least the length field being present but we know baseline is always 40 bytes of payload
+
+	getAllAlarmsRequest := "04454b0a000200000000000000000000000000000000000000000000000000000000000000000000"
+	getAllAlarmsResponse := "04452b0a000200000003000000000000000000000000000000000000000000000000000000000000"
+
+	getAllAlarmsNextRequest := "02344c0a000200000003000000000000000000000000000000000000000000000000000000000000"
+	getAllAlarmsNextResponse := "02342c0a00020000000b010280000000000000000000000000000000000000000000000000000000"
+
+	alarmNotification := "0000100a000b01048000000000000000000000000000000000000000000000000000000000000005"
+
+	frames := []string{
+		getAllAlarmsRequest,
+		getAllAlarmsResponse,
+		getAllAlarmsNextRequest,
+		getAllAlarmsNextResponse,
+		alarmNotification,
+	}
+	for _, frame := range frames {
+		data, err := stringToPacket(frame)
+		assert.NoError(t, err)
+
+		packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+		assert.NotNil(t, packet)
+
+		omciLayer := packet.Layer(LayerTypeOMCI)
+		assert.NotNil(t, omciLayer)
+	}
+}
+
+func TestDecodesFrameTooSmall(t *testing.T) {
+	// Less than 4 (so cannot determine message set)
+	veryShort := "04454b"
+
+	// Baseline message set checks (only 39 bytes)
+	// Extended message set checks (only 1 octet of 2 byte length field)
+	getAllAlarmsRequest := "04454b0a0002000000000000000000000000000000000000000000000000000000000000000000"
+	getAllAlarmsRequestExt := "04454b0b0002000000"
+	getAllAlarmsResponse := "04452b0a0002000000030000000000000000000000000000000000000000000000000000000000"
+	getAllAlarmsResponseExt := "04452b0b0002000000"
+
+	getAllAlarmsNextRequest := "02344c0a0002000000030000000000000000000000000000000000000000000000000000000000"
+	getAllAlarmsNextRequestExt := "02342c0b0002000000"
+	getAllAlarmsNextResponse := "02342c0a00020000000b0102800000000000000000000000000000000000000000000000000000"
+	getAllAlarmsNextResponseExt := "02342c0b0002000000"
+
+	alarmNotification := "0000100a000b010480000000000000000000000000000000000000000000000000000000000000"
+	alarmNotificationExt := "0000100b000b010400"
+
+	frames := []string{
+		veryShort,
+		getAllAlarmsRequest,
+		getAllAlarmsResponse,
+		getAllAlarmsNextRequest,
+		getAllAlarmsNextResponse,
+		alarmNotification,
+		getAllAlarmsRequestExt,
+		getAllAlarmsResponseExt,
+		getAllAlarmsNextRequestExt,
+		getAllAlarmsNextResponseExt,
+		alarmNotificationExt,
+	}
+	for _, frame := range frames {
+		data, err := stringToPacket(frame)
+		assert.NoError(t, err)
+
+		// Should get packet but with error layer
+		packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+		assert.NotNil(t, packet)
+		errLayer := packet.ErrorLayer()
+		assert.NotNil(t, errLayer)
+		metaData := packet.Metadata()
+		assert.NotNil(t, metaData)
+		assert.True(t, metaData.Truncated)
+
+		omciLayer := packet.Layer(LayerTypeOMCI)
+		assert.Nil(t, omciLayer)
+	}
+}
+
+func TestFrameWithUnknownMessageType(t *testing.T) {
+	frame := "00010b0a000200000000000000000000000000000000000000000000000000000000000000000000"
+
+	data, err := stringToPacket(frame)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+	errLayer := packet.ErrorLayer()
+	assert.NotNil(t, errLayer)
+	metaData := packet.Metadata()
+	assert.NotNil(t, metaData)
+	assert.False(t, metaData.Truncated)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+}
diff --git a/meframe.go b/meframe.go
deleted file mode 100644
index 472db31..0000000
--- a/meframe.go
+++ /dev/null
@@ -1,1536 +0,0 @@
-/*
- * Copyright (c) 2018 - present.  Boling Consulting Solutions (bcsw.net)
- *
- * 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.
- */
-/*
- * NOTE: This file was generated, manual edits will be overwritten!
- *
- * Generated by 'goCodeGenerator.py':
- *              https://github.com/opencord/omci-lib-go/OMCI-parser/README.md
- */
-
-package omci
-
-import (
-	"errors"
-	"fmt"
-	"github.com/deckarep/golang-set"
-	"github.com/google/gopacket"
-	me "github.com/opencord/omci-lib-go/generated"
-	"time"
-)
-
-var encoderMap map[MessageType]func(*me.ManagedEntity, options) (gopacket.SerializableLayer, error)
-
-func init() {
-	encoderMap = make(map[MessageType]func(*me.ManagedEntity, options) (gopacket.SerializableLayer, error))
-
-	encoderMap[CreateRequestType] = CreateRequestFrame
-	encoderMap[DeleteRequestType] = DeleteRequestFrame
-	encoderMap[SetRequestType] = SetRequestFrame
-	encoderMap[GetRequestType] = GetRequestFrame
-	encoderMap[GetAllAlarmsRequestType] = GetAllAlarmsRequestFrame
-	encoderMap[GetAllAlarmsNextRequestType] = GetAllAlarmsNextRequestFrame
-	encoderMap[MibUploadRequestType] = MibUploadRequestFrame
-	encoderMap[MibUploadNextRequestType] = MibUploadNextRequestFrame
-	encoderMap[MibResetRequestType] = MibResetRequestFrame
-	//encoderMap[TestRequestType] = TestRequestFrame
-	encoderMap[StartSoftwareDownloadRequestType] = StartSoftwareDownloadRequestFrame
-	encoderMap[DownloadSectionRequestType] = DownloadSectionRequestFrame
-	encoderMap[EndSoftwareDownloadRequestType] = EndSoftwareDownloadRequestFrame
-	encoderMap[ActivateSoftwareRequestType] = ActivateSoftwareRequestFrame
-	encoderMap[CommitSoftwareRequestType] = CommitSoftwareRequestFrame
-	encoderMap[SynchronizeTimeRequestType] = SynchronizeTimeRequestFrame
-	encoderMap[RebootRequestType] = RebootRequestFrame
-	encoderMap[GetNextRequestType] = GetNextRequestFrame
-	encoderMap[GetCurrentDataRequestType] = GetCurrentDataRequestFrame
-	encoderMap[SetTableRequestType] = SetTableRequestFrame
-	encoderMap[CreateResponseType] = CreateResponseFrame
-	encoderMap[DeleteResponseType] = DeleteResponseFrame
-	encoderMap[SetResponseType] = SetResponseFrame
-	encoderMap[GetResponseType] = GetResponseFrame
-	encoderMap[GetAllAlarmsResponseType] = GetAllAlarmsResponseFrame
-	encoderMap[GetAllAlarmsNextResponseType] = GetAllAlarmsNextResponseFrame
-	encoderMap[MibUploadResponseType] = MibUploadResponseFrame
-	encoderMap[MibUploadNextResponseType] = MibUploadNextResponseFrame
-	encoderMap[MibResetResponseType] = MibResetResponseFrame
-	//encoderMap[TestResponseType] = TestResponseFrame
-	encoderMap[StartSoftwareDownloadResponseType] = StartSoftwareDownloadResponseFrame
-	encoderMap[DownloadSectionResponseType] = DownloadSectionResponseFrame
-	encoderMap[EndSoftwareDownloadResponseType] = EndSoftwareDownloadResponseFrame
-	encoderMap[ActivateSoftwareResponseType] = ActivateSoftwareResponseFrame
-	encoderMap[CommitSoftwareResponseType] = CommitSoftwareResponseFrame
-	encoderMap[SynchronizeTimeResponseType] = SynchronizeTimeResponseFrame
-	encoderMap[RebootResponseType] = RebootResponseFrame
-	encoderMap[GetNextResponseType] = GetNextResponseFrame
-	encoderMap[GetCurrentDataResponseType] = GetCurrentDataResponseFrame
-	encoderMap[SetTableResponseType] = SetTableResponseFrame
-	encoderMap[AlarmNotificationType] = AlarmNotificationFrame
-	encoderMap[AttributeValueChangeType] = AttributeValueChangeFrame
-	//encoderMap[TestResultType] = TestResultFrame
-}
-
-type options struct {
-	frameFormat               DeviceIdent
-	failIfTruncated           bool
-	attributeMask             uint16
-	result                    me.Results      // Common for many responses
-	attrExecutionMask         uint16          // Create Response Only if results == 3 or Set Response only if results == 0
-	unsupportedMask           uint16          // Set Response only if results == 9
-	sequenceNumberCountOrSize uint16          // For get-next request frames and for frames that return number of commands or length
-	transactionID             uint16          // OMCI TID
-	mode                      uint8           // Get All Alarms retrieval mode
-	alarm                     AlarmOptions    // Alarm related frames
-	software                  SoftwareOptions // Software image related frames
-	payload                   interface{}     // ME or list of MEs, alarm bitmap, timestamp, ...
-	addDefaults               bool            // Add missing SetByCreate attributes for Create Requests
-}
-
-var defaultFrameOptions = options{
-	frameFormat:               BaselineIdent,
-	failIfTruncated:           false,
-	attributeMask:             0xFFFF,
-	result:                    me.Success,
-	attrExecutionMask:         0,
-	unsupportedMask:           0,
-	sequenceNumberCountOrSize: 0,
-	transactionID:             0,
-	mode:                      0,
-	software:                  defaultSoftwareOptions,
-	alarm:                     defaultAlarmOptions,
-	payload:                   nil,
-	addDefaults:               false,
-}
-
-// FrameOption sets options such as frame format, etc.
-type FrameOption func(*options)
-
-// FrameFormat determines determines the OMCI message format used on the fiber.
-// The default value is BaselineIdent
-func FrameFormat(ff DeviceIdent) FrameOption {
-	return func(o *options) {
-		o.frameFormat = ff
-	}
-}
-
-// FailIfTruncated determines whether a request to encode a frame that does
-// not have enough room for all requested options should fail and return an
-// error.
-//
-// If set to 'false', the behaviour depends on the message type/operation
-// requested. The table below provides more information:
-//
-//   Request Type	Behavour
-//	 ------------------------------------------------------------------------
-//	 CreateRequest  A single CreateRequest struct is always returned as the
-//                  CreateRequest message does not have an attributes Mask
-//                  field and a Baseline OMCI message is large enough to
-//                  support all Set-By-Create attributes.
-//
-//   GetResponse	If multiple OMCI response frames are needed to return
-//					all requested attributes, only the attributes that can
-//					fit will be returned and the FailedAttributeMask field
-//					set to the attributes that could not be returned
-//
-//					If this is an ME with an attribute that is a table, the
-//					first GetResponse struct will return the size of the
-//					attribute and the following GetNextResponse structs will
-//					contain the attribute data. The ONU application is
-//					responsible for stashing these extra struct(s) away in
-//					anticipation of possible GetNext Requests occurring for
-//					the attribute.  See the discussion on Table attributes
-//					in the GetResponse section of ITU G.988 for more
-//					information.
-//
-// If set to 'true', no struct(s) are returned and an error is provided.
-//
-// The default value is 'false'
-func FailIfTruncated(f bool) FrameOption {
-	return func(o *options) {
-		o.failIfTruncated = f
-	}
-}
-
-// attributeMask determines the attributes to encode into the frame.
-// The default value is 0xFFFF which specifies all available attributes
-// in the frame
-func AttributeMask(m uint16) FrameOption {
-	return func(o *options) {
-		o.attributeMask = m
-	}
-}
-
-// AttributeExecutionMask is used by the Create and Set Response frames to indicate
-// attributes that failed to be created/set.
-func AttributeExecutionMask(m uint16) FrameOption {
-	return func(o *options) {
-		o.attrExecutionMask = m
-	}
-}
-
-// UnsupportedAttributeMask is used by the Set Response frames to indicate
-// attributes are not supported on this ONU
-func UnsupportedAttributeMask(m uint16) FrameOption {
-	return func(o *options) {
-		o.unsupportedMask = m
-	}
-}
-
-// Result is used to set returned results in responses
-// that have that field
-func Result(r me.Results) FrameOption {
-	return func(o *options) {
-		o.result = r
-	}
-}
-
-// SequenceNumberCountOrSize is used by the GetNext and MibUploadGetNext request frames and for
-// frames that return number of commands or length such as Get (table attribute) or
-// MibUpload/GetAllAlarms/...
-func SequenceNumberCountOrSize(m uint16) FrameOption {
-	return func(o *options) {
-		o.sequenceNumberCountOrSize = m
-	}
-}
-
-// TransactionID is to specify the TID in the OMCI header. The default is
-// zero which requires the caller to set it to the appropriate value if this
-// is not an autonomous ONU notification frame
-func TransactionID(tid uint16) FrameOption {
-	return func(o *options) {
-		o.transactionID = tid
-	}
-}
-
-// RetrievalMode is to specify the the Alarm Retrieval Mode in a GetAllAlarms Request
-func RetrievalMode(m uint8) FrameOption {
-	return func(o *options) {
-		o.mode = m
-	}
-}
-
-// SuccessResult is to specify the the SuccessResult for a SynchronizeTime Response
-func SuccessResult(m uint8) FrameOption {
-	return func(o *options) {
-		o.mode = m
-	}
-}
-
-// RebootCondition is to specify the the Reboot Condition for a ONU Reboot request
-func RebootCondition(m uint8) FrameOption {
-	return func(o *options) {
-		o.mode = m
-	}
-}
-
-// Alarm is used to specify a collection of options related to Alarm notifications
-func Alarm(ao AlarmOptions) FrameOption {
-	return func(o *options) {
-		o.alarm = ao
-	}
-}
-
-// Software is used to specify a collection of options related to Software image
-// manipulation
-func Software(so SoftwareOptions) FrameOption {
-	return func(o *options) {
-		o.software = so
-	}
-}
-
-// Payload is used to specify ME payload options that are not simple types. This
-// include the ME (list of MEs) to encode into a GetNextMibUpload response, the
-// alarm bitmap for alarm relates responses/notifications, alarm bitmaps, and
-// for specifying the download section data when performing Software Download.
-func Payload(p interface{}) FrameOption {
-	return func(o *options) {
-		o.payload = p
-	}
-}
-
-// AddDefaults is used to specify that if a SetByCreate attribute is not
-// specified in the list of attributes for a Create Request, use the attribute
-// defined default
-func AddDefaults(add bool) FrameOption {
-	return func(o *options) {
-		o.addDefaults = add
-	}
-}
-
-// Alarm related frames have a wide variety of settable values. Placing them
-// in a separate struct is mainly to keep the base options simple
-type AlarmOptions struct {
-	AlarmClassID  me.ClassID
-	AlarmInstance uint16
-	AlarmBitmap   []byte // Should be up to 58 octets
-}
-
-var defaultAlarmOptions = AlarmOptions{
-	AlarmClassID:  0,
-	AlarmInstance: 0,
-	AlarmBitmap:   nil,
-}
-
-// Software related frames have a wide variety of settable values. Placing them
-// in a separate struct is mainly to keep the base options simple
-type SoftwareOptions struct {
-	WindowSize    uint8 // Window size - 1
-	SectionNumber uint8 // [0..Window size - 1]
-	ImageSize     uint32
-	CircuitPacks  []uint16 // slot (upper 8 bits) and instance (lower 8 bits)
-	Results       []DownloadResults
-	Data          []byte
-}
-
-var defaultSoftwareOptions = SoftwareOptions{
-	WindowSize:    0,
-	SectionNumber: 0,
-	ImageSize:     0,
-	CircuitPacks:  nil,
-	Results:       nil,
-	Data:          nil,
-}
-
-// EncodeFrame will encode the Managed Entity specific protocol struct and an
-// OMCILayer struct. This struct can be provided to the gopacket.SerializeLayers()
-// function to be serialized into a buffer for transmission.
-func EncodeFrame(m *me.ManagedEntity, messageType MessageType, opt ...FrameOption) (*OMCI, gopacket.SerializableLayer, error) {
-	// Check for message type support
-	msgType := me.MsgType(messageType & me.MsgTypeMask)
-	meDefinition := m.GetManagedEntityDefinition()
-
-	if !me.SupportsMsgType(meDefinition, msgType) {
-		msg := fmt.Sprintf("managed entity %v does not support %v Message-Type",
-			meDefinition.GetName(), msgType)
-		return nil, nil, errors.New(msg)
-	}
-	// Decode options
-	opts := defaultFrameOptions
-	for _, o := range opt {
-		o(&opts)
-	}
-	// TODO: If AttributesMask option passed in, check for deprecated options. Allow encoding option
-	//       that will ignore deprecated option.   Add additional in the get and set meframe_test,go
-	//       test functions to test this. Also have it test attribute name(s) to see if the attribute
-	//       is deprecated.  The OMCI-Parser now supports detection of deprecated attributes and
-	//       provides that to the code-generator (and currently available in generated golang code).
-	// Note: Transaction ID should be set before frame serialization
-	omci := &OMCI{
-		TransactionID:    opts.transactionID,
-		MessageType:      messageType,
-		DeviceIdentifier: opts.frameFormat,
-	}
-	var meInfo gopacket.SerializableLayer
-	var err error
-
-	if encoder, ok := encoderMap[messageType]; ok {
-		meInfo, err = encoder(m, opts)
-	} else {
-		err = fmt.Errorf("message-type: %v/%#x is not supported", messageType, messageType)
-	}
-	if err != nil {
-		return nil, nil, err
-	}
-	return omci, meInfo, err
-}
-
-// For most all create methods below, error checking for valid masks, attribute
-// values, and other fields is left to when the frame is actually serialized.
-
-func checkAttributeMask(m *me.ManagedEntity, mask uint16) (uint16, error) {
-	if mask == defaultFrameOptions.attributeMask {
-		// Scale back to just what is allowed
-		return m.GetAllowedAttributeMask(), nil
-	}
-	if mask&m.GetManagedEntityDefinition().GetAllowedAttributeMask() != mask {
-		return 0, errors.New("invalid attribute mask")
-	}
-	return mask & m.GetManagedEntityDefinition().GetAllowedAttributeMask(), nil
-}
-
-// return the maximum space that can be used by attributes
-func maxPacketAvailable(m *me.ManagedEntity, opt options) uint {
-	if opt.frameFormat == BaselineIdent {
-		// OMCI Header          - 4 octets
-		// Class ID/Instance ID - 4 octets
-		// Length field			- 4 octets
-		// MIC                  - 4 octets
-		return MaxBaselineLength - 16
-	}
-	// OMCI Header          - 4 octets
-	// Class ID/Instance ID - 4 octets
-	// Length field			- 2 octets
-	// MIC                  - 4 octets
-	return MaxExtendedLength - 14
-}
-
-func calculateAttributeMask(m *me.ManagedEntity, requestedMask uint16) (uint16, error) {
-	attrDefs := m.GetAttributeDefinitions()
-	var entityIDName string
-	if entry, ok := attrDefs[0]; ok {
-		entityIDName = entry.GetName()
-	} else {
-		panic("unexpected error") // All attribute definition maps have an entity ID
-	}
-	attributeNames := make([]interface{}, 0)
-	for attrName := range m.GetAttributeValueMap() {
-		if attrName == entityIDName {
-			continue // No mask for EntityID
-		}
-		attributeNames = append(attributeNames, attrName)
-	}
-	calculatedMask, err := me.GetAttributesBitmap(attrDefs, mapset.NewSetWith(attributeNames...))
-
-	if err != nil {
-		return 0, err
-	}
-	return calculatedMask & requestedMask, nil
-}
-
-// GenFrame is a helper function to make tests a little easier to read.
-// For a real application, use the .../omci/generated/class.go 'New'
-// functions to create your Managed Entity and then use it to call the
-// EncodeFrame method.
-func GenFrame(meInstance *me.ManagedEntity, messageType MessageType, options ...FrameOption) ([]byte, error) {
-	omciLayer, msgLayer, err := EncodeFrame(meInstance, messageType, options...)
-	if err != nil {
-		return nil, err
-	}
-	// Serialize the frame and send it
-	var serializeOptions gopacket.SerializeOptions
-	serializeOptions.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err = gopacket.SerializeLayers(buffer, serializeOptions, omciLayer, msgLayer)
-	if err != nil {
-		return nil, err
-	}
-	return buffer.Bytes(), nil
-}
-
-func CreateRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	// NOTE: The OMCI parser does not extract the default values of set-by-create attributes
-	//       and are the zero 'default' (or nil) at this time.  For this reason, make sure
-	//       you specify all non-zero default values and pass them in appropriate
-	meLayer := &CreateRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		Attributes: m.GetAttributeValueMap(),
-	}
-	// Add any missing SetByCreate options if requested
-	if opt.addDefaults {
-		if attrDefs, err := me.GetAttributesDefinitions(m.GetClassID()); err.StatusCode() == me.Success {
-			for index, attr := range attrDefs {
-				if me.SupportsAttributeAccess(attr, me.SetByCreate) {
-					if index == 0 {
-						continue // Skip Entity ID, if it is SetByCreate, they should always specify it
-					}
-					if _, found := meLayer.Attributes[attr.GetName()]; !found {
-						meLayer.Attributes[attr.GetName()] = attr.DefValue
-					}
-				}
-			}
-		}
-	}
-	return meLayer, nil
-}
-
-func CreateResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	meLayer := &CreateResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		Result: opt.result,
-	}
-	if meLayer.Result == me.ParameterError {
-		meLayer.AttributeExecutionMask = opt.attrExecutionMask
-	}
-	return meLayer, nil
-}
-
-func DeleteRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	meLayer := &DeleteRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-	}
-	return meLayer, nil
-}
-
-func DeleteResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	meLayer := &DeleteResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		Result: opt.result,
-	}
-	return meLayer, nil
-}
-
-func SetRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	mask, err := checkAttributeMask(m, opt.attributeMask)
-	if err != nil {
-		return nil, err
-	}
-	mask, err = calculateAttributeMask(m, mask)
-	if err != nil {
-		return nil, err
-	}
-	meDefinition := m.GetManagedEntityDefinition()
-	attrDefs := meDefinition.GetAttributeDefinitions()
-	attrMap := m.GetAttributeValueMap()
-
-	// Get payload space available
-	maxPayload := maxPacketAvailable(m, opt)
-	payloadAvailable := int(maxPayload) - 2 // Less attribute mask
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-		// payloadAvailable -= 2				// Less length
-	}
-	meLayer := &SetRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		AttributeMask: 0,
-		Attributes:    make(me.AttributeValueMap),
-	}
-	for mask != 0 {
-		// Iterate down the attributes (Attribute 0 is the ManagedEntity ID)
-		var attrIndex uint
-		for attrIndex = 1; attrIndex <= 16; attrIndex++ {
-			// Is this attribute requested
-			if mask&(1<<(16-attrIndex)) != 0 {
-				// Get definitions since we need the name
-				attrDef, ok := attrDefs[attrIndex]
-				if !ok {
-					msg := fmt.Sprintf("Unexpected error, index %v not valued for ME %v",
-						attrIndex, meDefinition.GetName())
-					return nil, errors.New(msg)
-				}
-				var attrValue interface{}
-				attrValue, ok = attrMap[attrDef.Name]
-				if !ok {
-					msg := fmt.Sprintf("Unexpected error, attribute %v not provided in ME %v: %v",
-						attrDef.GetName(), meDefinition.GetName(), m)
-					return nil, errors.New(msg)
-				}
-				// Is space available?
-				if attrDef.Size <= payloadAvailable {
-					// Mark bit handled
-					mask &= ^attrDef.Mask
-					meLayer.AttributeMask |= attrDef.Mask
-					meLayer.Attributes[attrDef.Name] = attrValue
-					payloadAvailable -= attrDef.Size
-				} else {
-					// TODO: Should we set truncate?
-					msg := fmt.Sprintf("out-of-space. Cannot fit attribute %v into SetRequest message",
-						attrDef.GetName())
-					return nil, me.NewMessageTruncatedError(msg)
-				}
-			}
-		}
-	}
-	if err == nil && meLayer.AttributeMask == 0 {
-		// TODO: Is a set request with no attributes valid?
-		return nil, errors.New("no attributes encoded for SetRequest")
-	}
-	return meLayer, nil
-}
-
-func SetResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	meLayer := &SetResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		Result: opt.result,
-	}
-	if meLayer.Result == me.AttributeFailure {
-		meLayer.UnsupportedAttributeMask = opt.unsupportedMask
-		meLayer.FailedAttributeMask = opt.attrExecutionMask
-	}
-	return meLayer, nil
-}
-
-func GetRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	// Given mask sent in (could be default of 0xFFFF) get what is allowable.
-	// This will be all allowed if 0xFFFF is passed in, or a subset if a fixed
-	// number of items.
-	maxMask, err := checkAttributeMask(m, opt.attributeMask)
-	if err != nil {
-		return nil, err
-	}
-	// Now scan attributes and reduce mask to only those requested
-	var mask uint16
-	mask, err = calculateAttributeMask(m, maxMask)
-	if err != nil {
-		return nil, err
-	}
-	if mask == 0 {
-		// TODO: Is a Get request with no attributes valid?
-		return nil, errors.New("no attributes requested for GetRequest")
-	}
-	meLayer := &GetRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		AttributeMask: mask,
-	}
-	return meLayer, nil
-}
-
-func GetResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	mask, err := checkAttributeMask(m, opt.attributeMask)
-	if err != nil {
-		return nil, err
-	}
-	mask, err = calculateAttributeMask(m, mask)
-	if err != nil {
-		return nil, err
-	}
-	meLayer := &GetResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		Result:        opt.result,
-		AttributeMask: 0,
-		Attributes:    make(me.AttributeValueMap),
-	}
-	if meLayer.Result == me.AttributeFailure {
-		meLayer.UnsupportedAttributeMask = opt.unsupportedMask
-		meLayer.FailedAttributeMask = opt.attrExecutionMask
-	}
-	// Encode whatever we can
-	if meLayer.Result == me.Success || meLayer.Result == me.AttributeFailure {
-		// Encode results
-		// Get payload space available
-		maxPayload := maxPacketAvailable(m, opt)
-		payloadAvailable := int(maxPayload) - 2 - 4 // Less attribute mask and attribute error encoding
-		meDefinition := m.GetManagedEntityDefinition()
-		attrDefs := meDefinition.GetAttributeDefinitions()
-		attrMap := m.GetAttributeValueMap()
-
-		if mask != 0 {
-			// Iterate down the attributes (Attribute 0 is the ManagedEntity ID)
-			var attrIndex uint
-			for attrIndex = 1; attrIndex <= 16; attrIndex++ {
-				// Is this attribute requested
-				if mask&(1<<(16-attrIndex)) != 0 {
-					// Get definitions since we need the name
-					attrDef, ok := attrDefs[attrIndex]
-					if !ok {
-						msg := fmt.Sprintf("Unexpected error, index %v not valued for ME %v",
-							attrIndex, meDefinition.GetName())
-						return nil, errors.New(msg)
-					}
-					var attrValue interface{}
-					attrValue, ok = attrMap[attrDef.Name]
-					if !ok {
-						msg := fmt.Sprintf("Unexpected error, attribute %v not provided in ME %v: %v",
-							attrDef.GetName(), meDefinition.GetName(), m)
-						return nil, errors.New(msg)
-					}
-					// Is space available?
-					if attrDef.Size <= payloadAvailable {
-						// Mark bit handled
-						mask &= ^attrDef.Mask
-						meLayer.AttributeMask |= attrDef.Mask
-						meLayer.Attributes[attrDef.Name] = attrValue
-						payloadAvailable -= attrDef.Size
-
-					} else if opt.failIfTruncated {
-						// TODO: Should we set truncate?
-						msg := fmt.Sprintf("out-of-space. Cannot fit attribute %v into GetResponse message",
-							attrDef.GetName())
-						return nil, me.NewMessageTruncatedError(msg)
-					} else {
-						// Add to existing 'failed' mask and update result
-						meLayer.FailedAttributeMask |= attrDef.Mask
-						meLayer.Result = me.AttributeFailure
-					}
-				}
-			}
-		}
-	}
-	return meLayer, nil
-}
-
-func GetAllAlarmsRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	// Common for all MEs
-	meLayer := &GetAllAlarmsRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		AlarmRetrievalMode: opt.mode,
-	}
-	return meLayer, nil
-}
-
-func GetAllAlarmsResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	// Common for all MEs
-	meLayer := &GetAllAlarmsResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		NumberOfCommands: opt.sequenceNumberCountOrSize,
-	}
-	return meLayer, nil
-}
-
-func GetAllAlarmsNextRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	// Common for all MEs
-	meLayer := &GetAllAlarmsNextRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		CommandSequenceNumber: opt.sequenceNumberCountOrSize,
-	}
-	return meLayer, nil
-}
-
-func GetAllAlarmsNextResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	// Common for all MEs
-	meLayer := &GetAllAlarmsNextResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		AlarmEntityClass:    opt.alarm.AlarmClassID,
-		AlarmEntityInstance: opt.alarm.AlarmInstance,
-	}
-	if len(opt.alarm.AlarmBitmap) > 28 {
-		return nil, errors.New("invalid Alarm Bitmap Size. Must be [0..27]")
-	}
-	for octet := 0; octet < len(opt.alarm.AlarmBitmap); octet++ {
-		meLayer.AlarmBitMap[octet] = opt.alarm.AlarmBitmap[octet]
-	}
-	for octet := len(opt.alarm.AlarmBitmap); octet < 28; octet++ {
-		meLayer.AlarmBitMap[octet] = 0
-	}
-	return meLayer, nil
-}
-
-func MibUploadRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	// Common for all MEs
-	meLayer := &MibUploadRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: 0,
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-	}
-	return meLayer, nil
-}
-
-func MibUploadResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	// Common for all MEs
-	meLayer := &MibUploadResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: 0,
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		NumberOfCommands: opt.sequenceNumberCountOrSize,
-	}
-	return meLayer, nil
-}
-
-func MibUploadNextRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	// Common for all MEs
-	meLayer := &MibUploadNextRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: 0,
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		CommandSequenceNumber: opt.sequenceNumberCountOrSize,
-	}
-	return meLayer, nil
-}
-
-func MibUploadNextResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	// Common for all MEs
-	meLayer := &MibUploadNextResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-	}
-	if opt.payload == nil {
-		// Shortcut used to specify the request sequence number is out of range, encode
-		// a ME instance with class ID of zero to specify this per ITU G.988
-		meDef := me.ManagedEntityDefinition{
-			Name:                 "InvalidSequenceNumberManagedEntity",
-			ClassID:              me.ClassID(0),
-			MessageTypes:         nil,
-			AttributeDefinitions: make(me.AttributeDefinitionMap),
-		}
-		opt.payload, _ = me.NewManagedEntity(meDef)
-	}
-	if _, ok := opt.payload.(*[]me.ManagedEntity); ok {
-		if opt.frameFormat == BaselineIdent {
-			return nil, errors.New("invalid payload for Baseline message")
-		}
-		// TODO: List of MEs. valid for extended messages only
-	} else if managedEntity, ok := opt.payload.(*me.ManagedEntity); ok {
-		// Single ME
-		meLayer.ReportedME = *managedEntity
-	} else {
-		return nil, errors.New("invalid payload for MibUploadNextResponse frame")
-	}
-	return meLayer, nil
-}
-
-func MibResetRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	// Common for all MEs
-	meLayer := &MibResetRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-	}
-	return meLayer, nil
-}
-
-func MibResetResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	// Common for all MEs
-	meLayer := &MibResetResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		Result: opt.result,
-	}
-	return meLayer, nil
-}
-
-func AlarmNotificationFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	mask, err := checkAttributeMask(m, opt.attributeMask)
-	if err != nil {
-		return nil, err
-	}
-	// Common for all MEs
-	meLayer := &AlarmNotificationMsg{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-	}
-	// Get payload space available
-	maxPayload := maxPacketAvailable(m, opt)
-	payloadAvailable := int(maxPayload) - 1 // Less alarm sequence number
-
-	// TODO: Lots of work to do
-	fmt.Println(mask, maxPayload, payloadAvailable)
-
-	return meLayer, errors.New("todo: Not implemented")
-}
-
-func AttributeValueChangeFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	mask, err := checkAttributeMask(m, opt.attributeMask)
-	if err != nil {
-		return nil, err
-	}
-	// Common for all MEs
-	meLayer := &AttributeValueChangeMsg{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		AttributeMask: 0,
-		Attributes:    make(me.AttributeValueMap),
-	}
-	// Get payload space available
-	maxPayload := maxPacketAvailable(m, opt)
-	payloadAvailable := int(maxPayload) - 2 // Less attribute mask
-
-	// TODO: Lots of work to do
-
-	fmt.Println(mask, maxPayload, payloadAvailable)
-	return meLayer, errors.New("todo: Not implemented")
-}
-
-//func TestRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-//	if opt.frameFormat == ExtendedIdent {
-//		return nil, errors.New("Extended message set for this message type is not supported")
-//	}
-//	mask, err := checkAttributeMask(m, opt.attributeMask)
-//	if err != nil {
-//		return nil, err
-//	}
-//	// Common for all MEs
-//	meLayer := &TestRequest{
-//		MeBasePacket: MeBasePacket{
-//			EntityClass:    m.GetClassID(),
-//			EntityInstance: m.GetEntityID(),
-//			Extended:       opt.frameFormat == ExtendedIdent,
-//		},
-//	}
-//	// Get payload space available
-//	maxPayload := maxPacketAvailable(m, opt)
-//
-//	// TODO: Lots of work to do
-//
-//	fmt.Println(mask, maxPayload)
-//	return meLayer, errors.New("todo: Not implemented")
-//}
-
-//func TestResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-//	if opt.frameFormat == ExtendedIdent {
-//		return nil, errors.New("Extended message set for this message type is not supported")
-//	}
-//	mask, err := checkAttributeMask(m, opt.attributeMask)
-//	if err != nil {
-//		return nil, err
-//	}
-//	// Common for all MEs
-//	meLayer := &TestResponse{
-//		MeBasePacket: MeBasePacket{
-//			EntityClass:    m.GetClassID(),
-//			EntityInstance: m.GetEntityID(),
-//			Extended:       opt.frameFormat == ExtendedIdent,
-//		},
-//	}
-//	// Get payload space available
-//	maxPayload := maxPacketAvailable(m, opt)
-//
-//	// TODO: Lots of work to do
-//
-//	fmt.Println(mask, maxPayload)
-//	return meLayer, errors.New("todo: Not implemented")
-//}
-
-func StartSoftwareDownloadRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	// Common for all MEs
-	meLayer := &StartSoftwareDownloadRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		WindowSize:           opt.software.WindowSize,
-		ImageSize:            opt.software.ImageSize,
-		NumberOfCircuitPacks: byte(len(opt.software.CircuitPacks)),
-		CircuitPacks:         opt.software.CircuitPacks,
-	}
-	// TODO: Add length check to insure we do not exceed maximum packet size
-	// payloadAvailable := int(maxPacketAvailable(m, opt))
-	payloadAvailable := 2
-	sizeNeeded := 1
-	if sizeNeeded > payloadAvailable {
-		// TODO: Should we set truncate?
-		msg := "out-of-space. Cannot fit Circuit Pack instances into Start Software Download Request message"
-		return nil, me.NewMessageTruncatedError(msg)
-	}
-	return meLayer, nil
-}
-
-func StartSoftwareDownloadResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	// Common for all MEs
-	meLayer := &StartSoftwareDownloadResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		WindowSize:        opt.software.WindowSize,
-		NumberOfInstances: byte(len(opt.software.CircuitPacks)),
-		MeResults:         opt.software.Results,
-	}
-	// TODO: Add length check to insure we do not exceed maximum packet size
-	// payloadAvailable := int(maxPacketAvailable(m, opt))
-	payloadAvailable := 2
-	sizeNeeded := 1
-	if sizeNeeded > payloadAvailable {
-		// TODO: Should we set truncate?
-		msg := "out-of-space. Cannot fit Results  into Start Software Download Response message"
-		return nil, me.NewMessageTruncatedError(msg)
-	}
-	return meLayer, nil
-}
-
-func DownloadSectionRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.software.Data == nil {
-		return nil, me.NewNonStatusError("Software image data missing")
-	}
-	// Common for all MEs
-	meLayer := &DownloadSectionRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		SectionNumber: opt.software.SectionNumber,
-		SectionData:   opt.software.Data,
-	}
-	return meLayer, nil
-}
-
-func DownloadSectionResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	// Common for all MEs
-	meLayer := &DownloadSectionResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		Result:        opt.result,
-		SectionNumber: opt.software.SectionNumber,
-	}
-	return meLayer, nil
-}
-
-func EndSoftwareDownloadRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	mask, err := checkAttributeMask(m, opt.attributeMask)
-	if err != nil {
-		return nil, err
-	}
-	// Common for all MEs
-	meLayer := &EndSoftwareDownloadRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-	}
-	// Get payload space available
-	maxPayload := maxPacketAvailable(m, opt)
-
-	// TODO: Lots of work to do
-
-	fmt.Println(mask, maxPayload)
-	return meLayer, errors.New("todo: Not implemented")
-}
-
-func EndSoftwareDownloadResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	mask, err := checkAttributeMask(m, opt.attributeMask)
-	if err != nil {
-		return nil, err
-	}
-	// Common for all MEs
-	meLayer := &EndSoftwareDownloadResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-	}
-	// Get payload space available
-	maxPayload := maxPacketAvailable(m, opt)
-
-	// TODO: Lots of work to do
-
-	fmt.Println(mask, maxPayload)
-	return meLayer, errors.New("todo: Not implemented")
-}
-
-func ActivateSoftwareRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	mask, err := checkAttributeMask(m, opt.attributeMask)
-	if err != nil {
-		return nil, err
-	}
-	// Common for all MEs
-	meLayer := &ActivateSoftwareRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-	}
-	// Get payload space available
-	maxPayload := maxPacketAvailable(m, opt)
-
-	// TODO: Lots of work to do
-
-	fmt.Println(mask, maxPayload)
-	return meLayer, errors.New("todo: Not implemented")
-}
-
-func ActivateSoftwareResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	mask, err := checkAttributeMask(m, opt.attributeMask)
-	if err != nil {
-		return nil, err
-	}
-	// Common for all MEs
-	meLayer := &ActivateSoftwareResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-	}
-	// Get payload space available
-	maxPayload := maxPacketAvailable(m, opt)
-
-	// TODO: Lots of work to do
-
-	fmt.Println(mask, maxPayload)
-	return meLayer, errors.New("todo: Not implemented")
-}
-
-func CommitSoftwareRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	mask, err := checkAttributeMask(m, opt.attributeMask)
-	if err != nil {
-		return nil, err
-	}
-	// Common for all MEs
-	meLayer := &CommitSoftwareRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-	}
-	// Get payload space available
-	maxPayload := maxPacketAvailable(m, opt)
-
-	// TODO: Lots of work to do
-
-	fmt.Println(mask, maxPayload)
-	return meLayer, errors.New("todo: Not implemented")
-}
-
-func CommitSoftwareResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	mask, err := checkAttributeMask(m, opt.attributeMask)
-	if err != nil {
-		return nil, err
-	}
-	// Common for all MEs
-	meLayer := &CommitSoftwareResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-	}
-	// Get payload space available
-	maxPayload := maxPacketAvailable(m, opt)
-
-	// TODO: Lots of work to do
-
-	fmt.Println(mask, maxPayload)
-	return meLayer, errors.New("todo: Not implemented")
-}
-
-func SynchronizeTimeRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	// Common for all MEs
-	meLayer := &SynchronizeTimeRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-	}
-	// Decode payload option. If nil, no timestamp provided
-	if timestamp, ok := opt.payload.(int64); ok {
-		tm := time.Unix(timestamp, 0)
-		meLayer.Year = uint16(tm.UTC().Year())
-		meLayer.Month = uint8(tm.UTC().Month())
-		meLayer.Day = uint8(tm.UTC().Day())
-		meLayer.Hour = uint8(tm.UTC().Hour())
-		meLayer.Minute = uint8(tm.UTC().Minute())
-		meLayer.Second = uint8(tm.UTC().Second())
-	}
-	return meLayer, nil
-}
-
-func SynchronizeTimeResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	// Common for all MEs
-	meLayer := &SynchronizeTimeResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		Result:         opt.result,
-		SuccessResults: opt.mode,
-	}
-	return meLayer, nil
-}
-
-func RebootRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	// Common for all MEs
-	meLayer := &RebootRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		RebootCondition: opt.mode,
-	}
-	return meLayer, nil
-}
-
-func RebootResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	// Common for all MEs
-	meLayer := &RebootResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		Result: opt.result,
-	}
-	return meLayer, nil
-}
-
-func GetNextRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	// Validate attribute mask
-	mask, err := checkAttributeMask(m, opt.attributeMask)
-	if err != nil {
-		return nil, err
-	}
-	// Now scan attributes and reduce mask to only those requested
-	mask, err = calculateAttributeMask(m, mask)
-	if err != nil {
-		return nil, err
-	}
-	if mask == 0 {
-		return nil, errors.New("no attributes requested for GetNextRequest")
-	}
-	// TODO: If more than one attribute or the attribute requested is not a table attribute, return an error
-	// Common for all MEs
-	meLayer := &GetNextRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		AttributeMask:  mask,
-		SequenceNumber: opt.sequenceNumberCountOrSize,
-	}
-	return meLayer, nil
-}
-
-func GetNextResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	// Validate attribute mask
-	mask, err := checkAttributeMask(m, opt.attributeMask)
-	if err != nil {
-		return nil, err
-	}
-	mask, err = calculateAttributeMask(m, mask)
-	if err != nil {
-		return nil, err
-	}
-	//
-	// Common for all MEs
-	meLayer := &GetNextResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-		Result:        opt.result,
-		AttributeMask: 0,
-		Attributes:    make(me.AttributeValueMap),
-	}
-	if meLayer.Result == me.Success {
-		// Get payload space available
-		maxPayload := maxPacketAvailable(m, opt)
-		payloadAvailable := int(maxPayload) - 3 // Less results and attribute mask
-		meDefinition := m.GetManagedEntityDefinition()
-		attrDefs := meDefinition.GetAttributeDefinitions()
-		attrMap := m.GetAttributeValueMap()
-
-		if mask == 0 {
-			return nil, errors.New("no attributes requested for GetNextResponse")
-		}
-		// TODO: If more than one attribute or the attribute requested is not a table attribute, return an error
-		// Iterate down the attributes (Attribute 0 is the ManagedEntity ID)
-		var attrIndex uint
-		for attrIndex = 1; attrIndex <= 16; attrIndex++ {
-			// Is this attribute requested
-			if mask&(1<<(16-attrIndex)) != 0 {
-				// Get definitions since we need the name
-				attrDef, ok := attrDefs[attrIndex]
-				if !ok {
-					msg := fmt.Sprintf("Unexpected error, index %v not valued for ME %v",
-						attrIndex, meDefinition.GetName())
-					return nil, errors.New(msg)
-				}
-				var attrValue interface{}
-				attrValue, ok = attrMap[attrDef.Name]
-				if !ok || attrValue == nil {
-					msg := fmt.Sprintf("Unexpected error, attribute %v not provided in ME %v: %v",
-						attrDef.GetName(), meDefinition.GetName(), m)
-					return nil, errors.New(msg)
-				}
-				// Is space available?
-				if attrDef.Size <= payloadAvailable {
-					// Mark bit handled
-					mask &= ^attrDef.Mask
-					meLayer.AttributeMask |= attrDef.Mask
-					meLayer.Attributes[attrDef.Name] = attrValue
-					payloadAvailable -= attrDef.Size
-				} else {
-					// TODO: Should we set truncate?
-					msg := fmt.Sprintf("out-of-space. Cannot fit attribute %v into GetNextResponse message",
-						attrDef.GetName())
-					return nil, me.NewMessageTruncatedError(msg)
-				}
-			}
-		}
-	}
-	return meLayer, nil
-}
-
-//func TestResultFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-//	if opt.frameFormat == ExtendedIdent {
-//		return nil, errors.New("Extended message set for this message type is not supported")
-//	}
-//	mask, err := checkAttributeMask(m, opt.attributeMask)
-//	if err != nil {
-//		return nil, err
-//	}
-//	// Common for all MEs
-//	meLayer := &TestResultNotification{
-//		MeBasePacket: MeBasePacket{
-//			EntityClass:    m.GetClassID(),
-//			EntityInstance: m.GetEntityID(),
-//			Extended:       opt.frameFormat == ExtendedIdent,
-//		},
-//	}
-//	// Get payload space available
-//	maxPayload := maxPacketAvailable(m, opt)
-//
-//	// TODO: Lots of work to do
-//
-//	fmt.Println(mask, maxPayload)
-//	return meLayer, errors.New("todo: Not implemented")
-//}
-
-func GetCurrentDataRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	mask, err := checkAttributeMask(m, opt.attributeMask)
-	if err != nil {
-		return nil, err
-	}
-	// Common for all MEs
-	meLayer := &GetCurrentDataRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-	}
-	// Get payload space available
-	maxPayload := maxPacketAvailable(m, opt)
-
-	// TODO: Lots of work to do
-
-	fmt.Println(mask, maxPayload)
-	return meLayer, errors.New("todo: Not implemented")
-}
-
-func GetCurrentDataResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	mask, err := checkAttributeMask(m, opt.attributeMask)
-	if err != nil {
-		return nil, err
-	}
-	// Common for all MEs
-	meLayer := &GetCurrentDataResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-	}
-	// Get payload space available
-	maxPayload := maxPacketAvailable(m, opt)
-
-	// TODO: Lots of work to do
-
-	fmt.Println(mask, maxPayload)
-	return meLayer, errors.New("todo: Not implemented")
-}
-
-func SetTableRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat != ExtendedIdent {
-		return nil, errors.New("SetTable message type only supported with Extended OMCI Messaging")
-	}
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	mask, err := checkAttributeMask(m, opt.attributeMask)
-	if err != nil {
-		return nil, err
-	}
-	// Common for all MEs
-	meLayer := &SetTableRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       opt.frameFormat == ExtendedIdent,
-		},
-	}
-	// Get payload space available
-	maxPayload := maxPacketAvailable(m, opt)
-
-	// TODO: Lots of work to do
-
-	fmt.Println(mask, maxPayload)
-	return meLayer, errors.New("todo: Not implemented")
-}
-
-func SetTableResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
-	if opt.frameFormat != ExtendedIdent {
-		return nil, errors.New("SetTable message type only supported with Extended OMCI Message Set")
-	}
-	if opt.frameFormat == ExtendedIdent {
-		return nil, errors.New("Extended message set for this message type is not supported")
-	}
-	mask, err := checkAttributeMask(m, opt.attributeMask)
-	if err != nil {
-		return nil, err
-	}
-	// Common for all MEs
-	meLayer := &SetTableResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    m.GetClassID(),
-			EntityInstance: m.GetEntityID(),
-			Extended:       true,
-		},
-	}
-	// Get payload space available
-	maxPayload := maxPacketAvailable(m, opt)
-
-	// TODO: Lots of work to do
-
-	fmt.Println(mask, maxPayload)
-	return meLayer, errors.New("todo: Not implemented")
-}
diff --git a/meframe/me_alarms.go b/meframe/me_alarms.go
new file mode 100644
index 0000000..ac0f242
--- /dev/null
+++ b/meframe/me_alarms.go
@@ -0,0 +1,126 @@
+/*
+ * 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 meframe
+
+import (
+	"errors"
+	"fmt"
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+func GetAllAlarmsRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	// Common for all MEs
+	meLayer := &GetAllAlarmsRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		AlarmRetrievalMode: opt.mode,
+	}
+	return meLayer, nil
+}
+
+func GetAllAlarmsResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	// Common for all MEs
+	meLayer := &GetAllAlarmsResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		NumberOfCommands: opt.sequenceNumberCountOrSize,
+	}
+	return meLayer, nil
+}
+
+func GetAllAlarmsNextRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	// Common for all MEs
+	meLayer := &GetAllAlarmsNextRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		CommandSequenceNumber: opt.sequenceNumberCountOrSize,
+	}
+	return meLayer, nil
+}
+
+func GetAllAlarmsNextResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	// Common for all MEs
+	meLayer := &GetAllAlarmsNextResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		AlarmEntityClass:    opt.alarm.AlarmClassID,
+		AlarmEntityInstance: opt.alarm.AlarmInstance,
+	}
+	if len(opt.alarm.AlarmBitmap) > 28 {
+		return nil, errors.New("invalid Alarm Bitmap Size. Must be [0..27]")
+	}
+	for octet := 0; octet < len(opt.alarm.AlarmBitmap); octet++ {
+		meLayer.AlarmBitMap[octet] = opt.alarm.AlarmBitmap[octet]
+	}
+	for octet := len(opt.alarm.AlarmBitmap); octet < 28; octet++ {
+		meLayer.AlarmBitMap[octet] = 0
+	}
+	return meLayer, nil
+}
+
+func AlarmNotificationFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	mask, err := checkAttributeMask(m, opt.attributeMask)
+	if err != nil {
+		return nil, err
+	}
+	// Common for all MEs
+	meLayer := &AlarmNotificationMsg{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+	}
+	// Get payload space available
+	maxPayload := maxPacketAvailable(m, opt)
+	payloadAvailable := int(maxPayload) - 1 // Less alarm sequence number
+
+	// TODO: Lots of work to do
+	fmt.Println(mask, maxPayload, payloadAvailable)
+
+	return meLayer, errors.New("todo: Not implemented")
+}
diff --git a/meframe/me_alarms_test.go b/meframe/me_alarms_test.go
new file mode 100644
index 0000000..8f410cf
--- /dev/null
+++ b/meframe/me_alarms_test.go
@@ -0,0 +1,223 @@
+/*
+ * 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 meframe_test
+
+import (
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/opencord/omci-lib-go/meframe"
+	"github.com/stretchr/testify/assert"
+	"math/rand"
+	"testing"
+)
+
+func testGetAllAlarmsRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	params := me.ParamData{
+		EntityID: uint16(0),
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+	mode := uint8(rand.Int31n(2))          // [0, 1]
+
+	frame, omciErr := meframe.GenFrame(meInstance, GetAllAlarmsRequestType, meframe.TransactionID(tid),
+		meframe.RetrievalMode(mode), meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, GetAllAlarmsRequestType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeGetAllAlarmsRequest)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*GetAllAlarmsRequest)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+	assert.Equal(t, mode, msgObj.AlarmRetrievalMode)
+}
+
+func testGetAllAlarmsResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	params := me.ParamData{
+		EntityID: uint16(0),
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	tid := uint16(rand.Int31n(0xFFFE) + 1)  // [1, 0xFFFF]
+	numOfCommands := uint16(rand.Int31n(5)) // [0, 5)
+
+	frame, omciErr := meframe.GenFrame(meInstance, GetAllAlarmsResponseType, meframe.TransactionID(tid),
+		meframe.SequenceNumberCountOrSize(numOfCommands), meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, GetAllAlarmsResponseType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeGetAllAlarmsResponse)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*GetAllAlarmsResponse)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+	assert.Equal(t, numOfCommands, msgObj.NumberOfCommands)
+}
+
+func testGetAllAlarmsNextRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	params := me.ParamData{
+		EntityID: uint16(0),
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	tid := uint16(rand.Int31n(0xFFFE) + 1)   // [1, 0xFFFF]
+	sequenceNumber := uint16(rand.Int31n(5)) // [0, 5)
+
+	frame, omciErr := meframe.GenFrame(meInstance, GetAllAlarmsNextRequestType, meframe.TransactionID(tid),
+		meframe.SequenceNumberCountOrSize(sequenceNumber), meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, GetAllAlarmsNextRequestType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeGetAllAlarmsNextRequest)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*GetAllAlarmsNextRequest)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+	assert.Equal(t, sequenceNumber, msgObj.CommandSequenceNumber)
+}
+
+func testGetAllAlarmsNextResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	params := me.ParamData{
+		EntityID: uint16(0),
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+
+	alarmInfo := meframe.AlarmOptions{
+		AlarmClassID:  123, // TODO: Real class here?
+		AlarmInstance: 456,
+		AlarmBitmap:   make([]byte, 28),
+	}
+	// TODO: Allow a 1 to 28 octet array to be used and zero fill any remainder...
+	for octet := 0; octet < 28; octet++ {
+		alarmInfo.AlarmBitmap[octet] = uint8(rand.Intn(256))
+	}
+	frame, omciErr := meframe.GenFrame(meInstance, GetAllAlarmsNextResponseType, meframe.TransactionID(tid),
+		meframe.Alarm(alarmInfo), meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, GetAllAlarmsNextResponseType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeGetAllAlarmsNextResponse)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*GetAllAlarmsNextResponse)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+	assert.Equal(t, alarmInfo.AlarmClassID, msgObj.AlarmEntityClass)
+	assert.Equal(t, alarmInfo.AlarmInstance, msgObj.AlarmEntityInstance)
+	for octet := 0; octet < len(alarmInfo.AlarmBitmap); octet++ {
+		assert.Equal(t, alarmInfo.AlarmBitmap[octet], msgObj.AlarmBitMap[octet])
+	}
+}
+
+func testAlarmNotificationTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	// TODO: Implement
+}
diff --git a/meframe/me_avc.go b/meframe/me_avc.go
new file mode 100644
index 0000000..e91339f
--- /dev/null
+++ b/meframe/me_avc.go
@@ -0,0 +1,54 @@
+/*
+ * 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 meframe
+
+import (
+	"errors"
+	"fmt"
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+func AttributeValueChangeFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	mask, err := checkAttributeMask(m, opt.attributeMask)
+	if err != nil {
+		return nil, err
+	}
+	// Common for all MEs
+	meLayer := &AttributeValueChangeMsg{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		AttributeMask: 0,
+		Attributes:    make(me.AttributeValueMap),
+	}
+	// Get payload space available
+	maxPayload := maxPacketAvailable(m, opt)
+	payloadAvailable := int(maxPayload) - 2 // Less attribute mask
+
+	// TODO: Lots of work to do
+
+	fmt.Println(mask, maxPayload, payloadAvailable)
+	return meLayer, errors.New("todo: Not implemented")
+}
diff --git a/meframe/me_avc_test.go b/meframe/me_avc_test.go
new file mode 100644
index 0000000..ddf360d
--- /dev/null
+++ b/meframe/me_avc_test.go
@@ -0,0 +1,27 @@
+/*
+ * 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 meframe_test
+
+import (
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"testing"
+)
+
+func testAttributeValueChangeTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	// TODO: Implement
+}
diff --git a/meframe/me_create.go b/meframe/me_create.go
new file mode 100644
index 0000000..1f363ed
--- /dev/null
+++ b/meframe/me_create.go
@@ -0,0 +1,75 @@
+/*
+ * 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 meframe
+
+import (
+	"errors"
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+func CreateRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	// NOTE: The OMCI parser does not extract the default values of set-by-create attributes
+	//       and are the zero 'default' (or nil) at this time.  For this reason, make sure
+	//       you specify all non-zero default values and pass them in appropriate
+	meLayer := &CreateRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		Attributes: m.GetAttributeValueMap(),
+	}
+	// Add any missing SetByCreate options if requested
+	if opt.addDefaults {
+		if attrDefs, err := me.GetAttributesDefinitions(m.GetClassID()); err.StatusCode() == me.Success {
+			for index, attr := range attrDefs {
+				if me.SupportsAttributeAccess(attr, me.SetByCreate) {
+					if index == 0 {
+						continue // Skip Entity ID, if it is SetByCreate, they should always specify it
+					}
+					if _, found := meLayer.Attributes[attr.GetName()]; !found {
+						meLayer.Attributes[attr.GetName()] = attr.DefValue
+					}
+				}
+			}
+		}
+	}
+	return meLayer, nil
+}
+
+func CreateResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	meLayer := &CreateResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		Result: opt.result,
+	}
+	if meLayer.Result == me.ParameterError {
+		meLayer.AttributeExecutionMask = opt.attrExecutionMask
+	}
+	return meLayer, nil
+}
diff --git a/meframe/me_create_test.go b/meframe/me_create_test.go
new file mode 100644
index 0000000..5632af8
--- /dev/null
+++ b/meframe/me_create_test.go
@@ -0,0 +1,145 @@
+/*
+ * 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 meframe_test
+
+import (
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/opencord/omci-lib-go/meframe"
+	"github.com/stretchr/testify/assert"
+	"math/rand"
+	"testing"
+)
+
+func testCreateRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	// Generate the frame. Use a default Entity ID of zero, but for the
+	// OMCI library, we need to specify all supported Set-By-Create
+	params := me.ParamData{
+		EntityID:   uint16(0),
+		Attributes: make(me.AttributeValueMap, 0),
+	}
+	for _, attrDef := range managedEntity.GetAttributeDefinitions() {
+		if attrDef.Index == 0 {
+			continue // Skip entity ID, already specified
+
+		} else if attrDef.GetAccess().Contains(me.SetByCreate) {
+			params.Attributes[attrDef.GetName()] = pickAValue(attrDef)
+		}
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	frame, omciErr := meframe.GenFrame(meInstance, CreateRequestType, meframe.TransactionID(tid), meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, CreateRequestType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeCreateRequest)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*CreateRequest)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+	assert.Equal(t, meInstance.GetAttributeValueMap(), msgObj.Attributes)
+}
+
+func testCreateResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	params := me.ParamData{
+		EntityID: uint16(0),
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+	result := me.Results(rand.Int31n(7))   // [0, 6] Not all types will be tested
+
+	// Always pass a failure mask, but should only get encoded if result == ParameterError
+	var mask uint16
+	for _, attrDef := range managedEntity.GetAttributeDefinitions() {
+		if attrDef.Index == 0 {
+			continue // Skip entity ID, already specified
+
+		} else if attrDef.GetAccess().Contains(me.SetByCreate) {
+			// Random 20% chance this parameter was bad
+			if result == me.ParameterError && rand.Int31n(5) == 0 {
+				mask |= attrDef.Mask
+			}
+		}
+	}
+	frame, omciErr := meframe.GenFrame(meInstance, CreateResponseType,
+		meframe.TransactionID(tid), meframe.Result(result), meframe.AttributeExecutionMask(mask), meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, CreateResponseType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeCreateResponse)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*CreateResponse)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+	assert.Equal(t, result, msgObj.Result)
+
+	if result == me.ParameterError {
+		assert.Equal(t, mask, msgObj.AttributeExecutionMask)
+	} else {
+		assert.Zero(t, msgObj.AttributeExecutionMask)
+	}
+}
diff --git a/meframe/me_delete.go b/meframe/me_delete.go
new file mode 100644
index 0000000..0a5552f
--- /dev/null
+++ b/meframe/me_delete.go
@@ -0,0 +1,54 @@
+/*
+ * 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 meframe
+
+import (
+	"errors"
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+func DeleteRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	meLayer := &DeleteRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+	}
+	return meLayer, nil
+}
+
+func DeleteResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	meLayer := &DeleteResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		Result: opt.result,
+	}
+	return meLayer, nil
+}
diff --git a/meframe/me_delete_test.go b/meframe/me_delete_test.go
new file mode 100644
index 0000000..be0686e
--- /dev/null
+++ b/meframe/me_delete_test.go
@@ -0,0 +1,116 @@
+/*
+ * 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 meframe_test
+
+import (
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/opencord/omci-lib-go/meframe"
+	"github.com/stretchr/testify/assert"
+	"math/rand"
+	"testing"
+)
+
+func testDeleteRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	// Generate the frame. Use a default Entity ID of zero, but for the
+	// OMCI library, we need to specify all supported Set-By-Create
+	params := me.ParamData{
+		EntityID: uint16(0),
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+
+	frame, omciErr := meframe.GenFrame(meInstance, DeleteRequestType, meframe.TransactionID(tid), meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, DeleteRequestType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeDeleteRequest)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*DeleteRequest)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+}
+
+func testDeleteResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	params := me.ParamData{
+		EntityID: uint16(0),
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+	result := me.Results(rand.Int31n(7))   // [0, 6] Not all types will be tested
+
+	frame, omciErr := meframe.GenFrame(meInstance, DeleteResponseType, meframe.TransactionID(tid), meframe.Result(result),
+		meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, DeleteResponseType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeDeleteResponse)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*DeleteResponse)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+	assert.Equal(t, result, msgObj.Result)
+}
diff --git a/meframe/me_get.go b/meframe/me_get.go
new file mode 100644
index 0000000..f50e554
--- /dev/null
+++ b/meframe/me_get.go
@@ -0,0 +1,133 @@
+/*
+ * 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 meframe
+
+import (
+	"errors"
+	"fmt"
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+func GetRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	// Given mask sent in (could be default of 0xFFFF) get what is allowable.
+	// This will be all allowed if 0xFFFF is passed in, or a subset if a fixed
+	// number of items.
+	maxMask, err := checkAttributeMask(m, opt.attributeMask)
+	if err != nil {
+		return nil, err
+	}
+	// Now scan attributes and reduce mask to only those requested
+	var mask uint16
+	mask, err = calculateAttributeMask(m, maxMask)
+	if err != nil {
+		return nil, err
+	}
+	if mask == 0 {
+		// TODO: Is a Get request with no attributes valid?
+		return nil, errors.New("no attributes requested for GetRequest")
+	}
+	meLayer := &GetRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		AttributeMask: mask,
+	}
+	return meLayer, nil
+}
+
+func GetResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	mask, err := checkAttributeMask(m, opt.attributeMask)
+	if err != nil {
+		return nil, err
+	}
+	mask, err = calculateAttributeMask(m, mask)
+	if err != nil {
+		return nil, err
+	}
+	meLayer := &GetResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		Result:        opt.result,
+		AttributeMask: 0,
+		Attributes:    make(me.AttributeValueMap),
+	}
+	if meLayer.Result == me.AttributeFailure {
+		meLayer.UnsupportedAttributeMask = opt.unsupportedMask
+		meLayer.FailedAttributeMask = opt.attrExecutionMask
+	}
+	// Encode whatever we can
+	if meLayer.Result == me.Success || meLayer.Result == me.AttributeFailure {
+		// Encode results
+		// Get payload space available
+		maxPayload := maxPacketAvailable(m, opt)
+		payloadAvailable := int(maxPayload) - 2 - 4 // Less attribute mask and attribute error encoding
+		meDefinition := m.GetManagedEntityDefinition()
+		attrDefs := meDefinition.GetAttributeDefinitions()
+		attrMap := m.GetAttributeValueMap()
+
+		if mask != 0 {
+			// Iterate down the attributes (Attribute 0 is the ManagedEntity ID)
+			var attrIndex uint
+			for attrIndex = 1; attrIndex <= 16; attrIndex++ {
+				// Is this attribute requested
+				if mask&(1<<(16-attrIndex)) != 0 {
+					// Get definitions since we need the name
+					attrDef, ok := attrDefs[attrIndex]
+					if !ok {
+						msg := fmt.Sprintf("Unexpected error, index %v not valued for ME %v",
+							attrIndex, meDefinition.GetName())
+						return nil, errors.New(msg)
+					}
+					var attrValue interface{}
+					attrValue, ok = attrMap[attrDef.Name]
+					if !ok {
+						msg := fmt.Sprintf("Unexpected error, attribute %v not provided in ME %v: %v",
+							attrDef.GetName(), meDefinition.GetName(), m)
+						return nil, errors.New(msg)
+					}
+					// Is space available?
+					if attrDef.Size <= payloadAvailable {
+						// Mark bit handled
+						mask &= ^attrDef.Mask
+						meLayer.AttributeMask |= attrDef.Mask
+						meLayer.Attributes[attrDef.Name] = attrValue
+						payloadAvailable -= attrDef.Size
+
+					} else if opt.failIfTruncated {
+						// TODO: Should we set truncate?
+						msg := fmt.Sprintf("out-of-space. Cannot fit attribute %v into GetResponse message",
+							attrDef.GetName())
+						return nil, me.NewMessageTruncatedError(msg)
+					} else {
+						// Add to existing 'failed' mask and update result
+						meLayer.FailedAttributeMask |= attrDef.Mask
+						meLayer.Result = me.AttributeFailure
+					}
+				}
+			}
+		}
+	}
+	return meLayer, nil
+}
diff --git a/meframe/me_get_test.go b/meframe/me_get_test.go
new file mode 100644
index 0000000..6e10431
--- /dev/null
+++ b/meframe/me_get_test.go
@@ -0,0 +1,230 @@
+/*
+ * 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 meframe_test
+
+import (
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/opencord/omci-lib-go/meframe"
+	"github.com/stretchr/testify/assert"
+	"math/rand"
+	"testing"
+)
+
+func testGetRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	params := me.ParamData{
+		EntityID:   uint16(0),
+		Attributes: make(me.AttributeValueMap, 0),
+	}
+	attrDefs := managedEntity.GetAttributeDefinitions()
+	for _, attrDef := range attrDefs {
+		if attrDef.Index == 0 {
+			continue // Skip entity ID, already specified
+		} else if attrDef.GetAccess().Contains(me.Read) {
+			// Allow 'nil' as parameter value for GetRequests since we only need names
+			params.Attributes[attrDef.GetName()] = nil
+		}
+	}
+	assert.NotEmpty(t, params.Attributes) // Need a parameter that is a table attribute
+	bitmask, attrErr := me.GetAttributesBitmap(attrDefs, getAttributeNameSet(params.Attributes))
+	assert.Nil(t, attrErr)
+
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+
+	frame, omciErr := meframe.GenFrame(meInstance, GetRequestType, meframe.TransactionID(tid),
+		meframe.AttributeMask(bitmask), meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, GetRequestType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeGetRequest)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*GetRequest)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+	assert.Equal(t, meInstance.GetAttributeMask(), msgObj.AttributeMask)
+}
+
+func testGetResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	params := me.ParamData{
+		EntityID:   uint16(0),
+		Attributes: make(me.AttributeValueMap),
+	}
+	// Add loop to test all valid result codes for this message type
+	validResultCodes := []me.Results{
+		me.Success,
+		me.ProcessingError,
+		me.NotSupported,
+		me.ParameterError,
+		me.UnknownEntity,
+		me.UnknownInstance,
+		me.DeviceBusy,
+		me.AttributeFailure,
+	}
+	for _, result := range validResultCodes {
+		tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+
+		// If success Results selected, set FailIfTruncated 50% of time to test
+		// overflow detection and failures periodically.  This is primarily for
+		// baseline message set for those MEs that may have lots of attribute space
+		// needed.  If extended message set, always fail if truncated since we should
+		// be able to stuff as much as we want (at least for now in these unit tests)
+		failIfTruncated := false
+		if result == me.Success && (rand.Int31n(2) == 1 || messageSet == ExtendedIdent) {
+			failIfTruncated = true
+		}
+		// Always pass a failure mask, but should only get encoded if result == ParameterError
+		var unsupportedMask uint16
+		var failedMask uint16
+		attrDefs := managedEntity.GetAttributeDefinitions()
+		for _, attrDef := range attrDefs {
+			if attrDef.Index == 0 {
+				continue // Skip entity ID, already specified
+
+			} else if attrDef.GetAccess().Contains(me.Read) {
+				// Random 5% chance this parameter unsupported and
+				// 5% it failed
+				switch rand.Int31n(20) {
+				default:
+					// TODO: Table attributes not yet supported.  For Table Attributes, figure out a
+					//       good way to unit test this and see if that can be extended to a more
+					//       general operation that provides the 'get-next' frames to the caller who
+					//		 wishes to serialize a table attribute.
+					if !attrDef.IsTableAttribute() {
+						params.Attributes[attrDef.GetName()] = pickAValue(attrDef)
+					}
+				case 0:
+					unsupportedMask |= attrDef.Mask
+				case 1:
+					failedMask |= attrDef.Mask
+				}
+			}
+		}
+		bitmask, attrErr := me.GetAttributesBitmap(attrDefs, getAttributeNameSet(params.Attributes))
+		assert.Nil(t, attrErr)
+
+		// Create the managed instance
+		meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+
+		frame, omciErr := meframe.GenFrame(meInstance, GetResponseType,
+			meframe.TransactionID(tid), meframe.Result(result),
+			meframe.AttributeMask(bitmask), meframe.FrameFormat(messageSet),
+			meframe.AttributeExecutionMask(failedMask),
+			meframe.UnsupportedAttributeMask(unsupportedMask),
+			meframe.FailIfTruncated(failIfTruncated))
+
+		// TODO: Need to test if err is MessageTruncatedError. Sometimes reported as
+		//       a proessing error
+		if omciErr != nil {
+			if _, ok := omciErr.(*me.MessageTruncatedError); ok {
+				return
+			}
+		}
+		assert.NotNil(t, frame)
+		assert.NotZero(t, len(frame))
+		assert.NotNil(t, err)
+		assert.Equal(t, err.StatusCode(), me.Success)
+
+		///////////////////////////////////////////////////////////////////
+		// Now decode and compare
+		packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+		assert.NotNil(t, packet)
+
+		omciLayer := packet.Layer(LayerTypeOMCI)
+		assert.NotNil(t, omciLayer)
+
+		omciObj, omciOk := omciLayer.(*OMCI)
+		assert.NotNil(t, omciObj)
+		assert.True(t, omciOk)
+		assert.Equal(t, tid, omciObj.TransactionID)
+		assert.Equal(t, GetResponseType, omciObj.MessageType)
+		assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+		msgLayer := packet.Layer(LayerTypeGetResponse)
+		// If requested Result was Success and FailIfTruncated is true, then we may
+		// fail (get nil layer) if too many attributes to fit in a frame
+		if result == me.Success && msgLayer == nil {
+			return // was expected
+		}
+		assert.NotNil(t, msgLayer)
+
+		msgObj, msgOk := msgLayer.(*GetResponse)
+		assert.NotNil(t, msgObj)
+		assert.True(t, msgOk)
+
+		assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+		assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+
+		switch msgObj.Result {
+		default:
+			assert.Equal(t, result, msgObj.Result)
+			assert.Zero(t, msgObj.FailedAttributeMask)
+			assert.Zero(t, msgObj.UnsupportedAttributeMask)
+
+		case me.Success:
+			assert.Equal(t, result, msgObj.Result)
+			assert.Zero(t, msgObj.FailedAttributeMask)
+			assert.Zero(t, msgObj.UnsupportedAttributeMask)
+			assert.Equal(t, meInstance.GetAttributeValueMap(), msgObj.Attributes)
+
+		case me.AttributeFailure:
+			// Should have been Success or AttributeFailure to start with
+			assert.True(t, result == me.Success || result == me.AttributeFailure)
+			if result == me.AttributeFailure {
+				assert.Equal(t, unsupportedMask, msgObj.UnsupportedAttributeMask)
+			}
+			// Returned may have more bits set in failed mask and less attributes
+			// since failIfTruncated is false and we may add more fail attributes
+			// since they do not fit. May also set only lower value (lower bits)
+			// if it turns out that the upper bits are already pre-assigned to the
+			// failure bits.
+			//
+			// Make sure any successful attributes were requested
+			meMap := meInstance.GetAttributeValueMap()
+			for name := range msgObj.Attributes {
+				getValue, ok := meMap[name]
+				assert.True(t, ok)
+				assert.NotNil(t, getValue)
+			}
+		}
+	}
+}
diff --git a/meframe/me_getcurrent.go b/meframe/me_getcurrent.go
new file mode 100644
index 0000000..359a717
--- /dev/null
+++ b/meframe/me_getcurrent.go
@@ -0,0 +1,76 @@
+/*
+ * 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 meframe
+
+import (
+	"errors"
+	"fmt"
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+func GetCurrentDataRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	mask, err := checkAttributeMask(m, opt.attributeMask)
+	if err != nil {
+		return nil, err
+	}
+	// Common for all MEs
+	meLayer := &GetCurrentDataRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+	}
+	// Get payload space available
+	maxPayload := maxPacketAvailable(m, opt)
+
+	// TODO: Lots of work to do
+
+	fmt.Println(mask, maxPayload)
+	return meLayer, errors.New("todo: Not implemented")
+}
+
+func GetCurrentDataResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	mask, err := checkAttributeMask(m, opt.attributeMask)
+	if err != nil {
+		return nil, err
+	}
+	// Common for all MEs
+	meLayer := &GetCurrentDataResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+	}
+	// Get payload space available
+	maxPayload := maxPacketAvailable(m, opt)
+
+	// TODO: Lots of work to do
+
+	fmt.Println(mask, maxPayload)
+	return meLayer, errors.New("todo: Not implemented")
+}
diff --git a/meframe/me_getcurrent_test.go b/meframe/me_getcurrent_test.go
new file mode 100644
index 0000000..9c9452b
--- /dev/null
+++ b/meframe/me_getcurrent_test.go
@@ -0,0 +1,31 @@
+/*
+ * 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 meframe_test
+
+import (
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"testing"
+)
+
+func testGetCurrentDataRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	// TODO: Implement
+}
+
+func testGetCurrentDataResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	// TODO: Implement
+}
diff --git a/meframe/me_getnext.go b/meframe/me_getnext.go
new file mode 100644
index 0000000..090b333
--- /dev/null
+++ b/meframe/me_getnext.go
@@ -0,0 +1,132 @@
+/*
+ * 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 meframe
+
+import (
+	"errors"
+	"fmt"
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+func GetNextRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	// Validate attribute mask
+	mask, err := checkAttributeMask(m, opt.attributeMask)
+	if err != nil {
+		return nil, err
+	}
+	// Now scan attributes and reduce mask to only those requested
+	mask, err = calculateAttributeMask(m, mask)
+	if err != nil {
+		return nil, err
+	}
+	if mask == 0 {
+		return nil, errors.New("no attributes requested for GetNextRequest")
+	}
+	// TODO: If more than one attribute or the attribute requested is not a table attribute, return an error
+	// Common for all MEs
+	meLayer := &GetNextRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		AttributeMask:  mask,
+		SequenceNumber: opt.sequenceNumberCountOrSize,
+	}
+	return meLayer, nil
+}
+
+func GetNextResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	// Validate attribute mask
+	mask, err := checkAttributeMask(m, opt.attributeMask)
+	if err != nil {
+		return nil, err
+	}
+	mask, err = calculateAttributeMask(m, mask)
+	if err != nil {
+		return nil, err
+	}
+	//
+	// Common for all MEs
+	meLayer := &GetNextResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		Result:        opt.result,
+		AttributeMask: 0,
+		Attributes:    make(me.AttributeValueMap),
+	}
+	if meLayer.Result == me.Success {
+		// Get payload space available
+		maxPayload := maxPacketAvailable(m, opt)
+		payloadAvailable := int(maxPayload) - 3 // Less results and attribute mask
+		meDefinition := m.GetManagedEntityDefinition()
+		attrDefs := meDefinition.GetAttributeDefinitions()
+		attrMap := m.GetAttributeValueMap()
+
+		if mask == 0 {
+			return nil, errors.New("no attributes requested for GetNextResponse")
+		}
+		// TODO: If more than one attribute or the attribute requested is not a table attribute, return an error
+		// Iterate down the attributes (Attribute 0 is the ManagedEntity ID)
+		var attrIndex uint
+		for attrIndex = 1; attrIndex <= 16; attrIndex++ {
+			// Is this attribute requested
+			if mask&(1<<(16-attrIndex)) != 0 {
+				// Get definitions since we need the name
+				attrDef, ok := attrDefs[attrIndex]
+				if !ok {
+					msg := fmt.Sprintf("Unexpected error, index %v not valued for ME %v",
+						attrIndex, meDefinition.GetName())
+					return nil, errors.New(msg)
+				}
+				var attrValue interface{}
+				attrValue, ok = attrMap[attrDef.Name]
+				if !ok || attrValue == nil {
+					msg := fmt.Sprintf("Unexpected error, attribute %v not provided in ME %v: %v",
+						attrDef.GetName(), meDefinition.GetName(), m)
+					return nil, errors.New(msg)
+				}
+				// Is space available?
+				if attrDef.Size <= payloadAvailable {
+					// Mark bit handled
+					mask &= ^attrDef.Mask
+					meLayer.AttributeMask |= attrDef.Mask
+					meLayer.Attributes[attrDef.Name] = attrValue
+					payloadAvailable -= attrDef.Size
+				} else {
+					// TODO: Should we set truncate?
+					msg := fmt.Sprintf("out-of-space. Cannot fit attribute %v into GetNextResponse message",
+						attrDef.GetName())
+					return nil, me.NewMessageTruncatedError(msg)
+				}
+			}
+		}
+	}
+	return meLayer, nil
+}
diff --git a/meframe/me_getnext_test.go b/meframe/me_getnext_test.go
new file mode 100644
index 0000000..6db557e
--- /dev/null
+++ b/meframe/me_getnext_test.go
@@ -0,0 +1,201 @@
+/*
+ * 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 meframe_test
+
+import (
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/opencord/omci-lib-go/meframe"
+	"github.com/stretchr/testify/assert"
+	"math/rand"
+	"testing"
+)
+
+func testGetNextRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	params := me.ParamData{
+		EntityID:   uint16(0),
+		Attributes: make(me.AttributeValueMap, 0),
+	}
+	// TODO: Loop over all table attributes for this class ID
+	// Find first attribute that is a table definition
+	// TODO: Test request of more than 1 attribute. G.988 specifies that a status
+	//       code of (3) should be returned.  Raise error during encode instead of
+	//       waiting for compliant ONU.  May want to have an 'ignore' to allow it.
+	attrDefs := managedEntity.GetAttributeDefinitions()
+	for _, attrDef := range attrDefs {
+		if attrDef.Index == 0 {
+			continue // Skip entity ID, already specified
+		} else if attrDef.IsTableAttribute() {
+			// TODO: Tables without a size are not supported. At least needs to be one octet
+			if attrDef.Size == 0 {
+				continue
+			}
+			// Allow 'nil' as parameter value for GetNextRequests since we only need names
+			params.Attributes[attrDef.GetName()] = nil
+			break
+		}
+	}
+	if len(params.Attributes) == 0 {
+		return
+	}
+	bitmask, attrErr := me.GetAttributesBitmap(attrDefs, getAttributeNameSet(params.Attributes))
+	assert.Nil(t, attrErr)
+
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	seqNumber := uint16(rand.Int31n(0xFFFF)) // [0, 0xFFFE]
+	tid := uint16(rand.Int31n(0xFFFE) + 1)   // [1, 0xFFFF]
+
+	frame, omciErr := meframe.GenFrame(meInstance, GetNextRequestType, meframe.TransactionID(tid),
+		meframe.SequenceNumberCountOrSize(seqNumber), meframe.AttributeMask(bitmask), meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, GetNextRequestType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeGetNextRequest)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*GetNextRequest)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+	assert.Equal(t, meInstance.GetAttributeMask(), msgObj.AttributeMask)
+	assert.Equal(t, seqNumber, msgObj.SequenceNumber)
+}
+
+func testGetNextResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	params := me.ParamData{
+		EntityID:   uint16(0),
+		Attributes: make(me.AttributeValueMap, 0),
+	}
+	// TODO: Loop over result types (here and other responses with results)
+	result := me.Success // me.Results(rand.Int31n(7))  // [0, 6]
+	bitmask := uint16(0)
+	attrDefs := managedEntity.GetAttributeDefinitions()
+
+	// TODO: Loop over all table attributes for this class ID
+	if result == me.Success {
+		// Find first attribute that is a table definition
+		// TODO: Test request of more than 1 attribute. G.988 specifies that a status
+		//       code of (3) should be returned.  Raise error during encode instead of
+		//       waiting for compliant ONU.  May want to have an 'ignore' to allow it.
+		for _, attrDef := range attrDefs {
+			if attrDef.Index == 0 {
+				continue // Skip entity ID, already specified
+			} else if attrDef.IsTableAttribute() {
+				if len(params.Attributes) == 0 {
+					// Need a parameter that is a table attribute
+					return
+				}
+				params.Attributes[attrDef.GetName()] = pickAValue(attrDef)
+				break
+			}
+		}
+		if len(params.Attributes) == 0 {
+			return
+		}
+		assert.NotEmpty(t, params.Attributes) // Need a parameter that is a table attribute
+		var attrErr error
+		bitmask, attrErr = me.GetAttributesBitmap(attrDefs, getAttributeNameSet(params.Attributes))
+		assert.Nil(t, attrErr)
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+
+	frame, omciErr := meframe.GenFrame(meInstance, GetNextResponseType, meframe.TransactionID(tid), meframe.Result(result),
+		meframe.AttributeMask(bitmask), meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	cid := meInstance.GetClassID()
+	assert.NotEqual(t, cid, 0)
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, GetNextResponseType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeGetNextResponse)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*GetNextResponse)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+	assert.Equal(t, meInstance.GetAttributeMask(), msgObj.AttributeMask)
+
+	switch msgObj.Result {
+	default:
+		assert.Equal(t, result, msgObj.Result)
+
+	case me.Success:
+		assert.Equal(t, result, msgObj.Result)
+		// The attributes should be equal but for variable length table attribute (size = 0 in structure)
+		// we will have the frame padding returned as well.
+		for attrName, value := range meInstance.GetAttributeValueMap() {
+			attr, err := me.GetAttributeDefinitionByName(attrDefs, attrName)
+			assert.Nil(t, err)
+			assert.NotNil(t, attr)
+			assert.Equal(t, attrName, attr.GetName())
+			if attr.IsTableAttribute() {
+				instValue := value.([]byte)
+				msgValue := msgObj.Attributes[attrName].([]byte)
+				assert.True(t, len(instValue) <= len(msgValue))
+				assert.Equal(t, msgValue[:len(instValue)], instValue)
+			} else {
+				assert.Equal(t, value, msgObj.Attributes[attrName])
+			}
+		}
+	}
+}
diff --git a/meframe/me_mibreset.go b/meframe/me_mibreset.go
new file mode 100644
index 0000000..78aab84
--- /dev/null
+++ b/meframe/me_mibreset.go
@@ -0,0 +1,56 @@
+/*
+ * 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 meframe
+
+import (
+	"errors"
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+func MibResetRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	// Common for all MEs
+	meLayer := &MibResetRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+	}
+	return meLayer, nil
+}
+
+func MibResetResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	// Common for all MEs
+	meLayer := &MibResetResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		Result: opt.result,
+	}
+	return meLayer, nil
+}
diff --git a/meframe/me_mibreset_test.go b/meframe/me_mibreset_test.go
new file mode 100644
index 0000000..3c58bcc
--- /dev/null
+++ b/meframe/me_mibreset_test.go
@@ -0,0 +1,114 @@
+/*
+ * 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 meframe_test
+
+import (
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/opencord/omci-lib-go/meframe"
+	"github.com/stretchr/testify/assert"
+	"math/rand"
+	"testing"
+)
+
+func testMibResetRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	params := me.ParamData{
+		EntityID: uint16(0),
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+
+	frame, omciErr := meframe.GenFrame(meInstance, MibResetRequestType, meframe.TransactionID(tid), meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, MibResetRequestType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeMibResetRequest)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*MibResetRequest)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+}
+
+func testMibResetResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	params := me.ParamData{
+		EntityID: uint16(0),
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+	result := me.Results(rand.Int31n(7))   // [0, 6] Not all types will be tested
+
+	frame, omciErr := meframe.GenFrame(meInstance, MibResetResponseType, meframe.TransactionID(tid),
+		meframe.Result(result), meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, MibResetResponseType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeMibResetResponse)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*MibResetResponse)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+	assert.Equal(t, result, msgObj.Result)
+}
diff --git a/meframe/me_mibupload.go b/meframe/me_mibupload.go
new file mode 100644
index 0000000..1b1dab9
--- /dev/null
+++ b/meframe/me_mibupload.go
@@ -0,0 +1,109 @@
+/*
+ * 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 meframe
+
+import (
+	"errors"
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+func MibUploadRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	// Common for all MEs
+	meLayer := &MibUploadRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: 0,
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+	}
+	return meLayer, nil
+}
+
+func MibUploadResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	// Common for all MEs
+	meLayer := &MibUploadResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: 0,
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		NumberOfCommands: opt.sequenceNumberCountOrSize,
+	}
+	return meLayer, nil
+}
+
+func MibUploadNextRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	// Common for all MEs
+	meLayer := &MibUploadNextRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: 0,
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		CommandSequenceNumber: opt.sequenceNumberCountOrSize,
+	}
+	return meLayer, nil
+}
+
+func MibUploadNextResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	// Common for all MEs
+	meLayer := &MibUploadNextResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+	}
+	if opt.payload == nil {
+		// Shortcut used to specify the request sequence number is out of range, encode
+		// a ME instance with class ID of zero to specify this per ITU G.988
+		meDef := me.ManagedEntityDefinition{
+			Name:                 "InvalidSequenceNumberManagedEntity",
+			ClassID:              me.ClassID(0),
+			MessageTypes:         nil,
+			AttributeDefinitions: make(me.AttributeDefinitionMap),
+		}
+		opt.payload, _ = me.NewManagedEntity(meDef)
+	}
+	if _, ok := opt.payload.(*[]me.ManagedEntity); ok {
+		if opt.frameFormat == BaselineIdent {
+			return nil, errors.New("invalid payload for Baseline message")
+		}
+		// TODO: List of MEs. valid for extended messages only
+	} else if managedEntity, ok := opt.payload.(*me.ManagedEntity); ok {
+		// Single ME
+		meLayer.ReportedME = *managedEntity
+	} else {
+		return nil, errors.New("invalid payload for MibUploadNextResponse frame")
+	}
+	return meLayer, nil
+}
diff --git a/meframe/me_mibupload_test.go b/meframe/me_mibupload_test.go
new file mode 100644
index 0000000..d278682
--- /dev/null
+++ b/meframe/me_mibupload_test.go
@@ -0,0 +1,208 @@
+/*
+ * 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 meframe_test
+
+import (
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/opencord/omci-lib-go/meframe"
+	"github.com/stretchr/testify/assert"
+	"math/rand"
+	"testing"
+)
+
+func testMibUploadRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	params := me.ParamData{
+		EntityID: uint16(0),
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+
+	frame, omciErr := meframe.GenFrame(meInstance, MibUploadRequestType, meframe.TransactionID(tid), meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, MibUploadRequestType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeMibUploadRequest)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*MibUploadRequest)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+}
+
+func testMibUploadResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	params := me.ParamData{
+		EntityID: uint16(0),
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	tid := uint16(rand.Int31n(0xFFFE) + 1)  // [1, 0xFFFF]
+	numOfCommands := uint16(rand.Int31n(5)) // [0, 5)
+
+	frame, omciErr := meframe.GenFrame(meInstance, MibUploadResponseType, meframe.TransactionID(tid),
+		meframe.SequenceNumberCountOrSize(numOfCommands), meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, MibUploadResponseType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeMibUploadResponse)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*MibUploadResponse)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+	assert.Equal(t, numOfCommands, msgObj.NumberOfCommands)
+}
+
+func testMibUploadNextRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	params := me.ParamData{
+		EntityID: uint16(0),
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	seqNumber := uint16(rand.Int31n(0xFFFF)) // [0, 0xFFFE]
+	tid := uint16(rand.Int31n(0xFFFE) + 1)   // [1, 0xFFFF]
+
+	var frame []byte
+	frame, omciErr := meframe.GenFrame(meInstance, MibUploadNextRequestType, meframe.TransactionID(tid),
+		meframe.SequenceNumberCountOrSize(seqNumber), meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, MibUploadNextRequestType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeMibUploadNextRequest)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*MibUploadNextRequest)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, seqNumber, msgObj.CommandSequenceNumber)
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+}
+
+func testMibUploadNextResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	params := me.ParamData{
+		EntityID: uint16(0),
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+
+	// TODO: Since only baseline messages supported, send only one ME
+	uploadMe := meInstance
+
+	frame, omciErr := meframe.GenFrame(meInstance, MibUploadNextResponseType, meframe.TransactionID(tid),
+		meframe.Payload(uploadMe), meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, MibUploadNextResponseType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeMibUploadNextResponse)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*MibUploadNextResponse)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+	assert.Equal(t, uploadMe.GetClassID(), msgObj.ReportedME.GetClassID())
+	assert.Equal(t, uploadMe.GetEntityID(), msgObj.ReportedME.GetEntityID())
+}
diff --git a/meframe/me_reboot.go b/meframe/me_reboot.go
new file mode 100644
index 0000000..b4c23dc
--- /dev/null
+++ b/meframe/me_reboot.go
@@ -0,0 +1,57 @@
+/*
+ * 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 meframe
+
+import (
+	"errors"
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+func RebootRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	// Common for all MEs
+	meLayer := &RebootRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		RebootCondition: opt.mode,
+	}
+	return meLayer, nil
+}
+
+func RebootResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	// Common for all MEs
+	meLayer := &RebootResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		Result: opt.result,
+	}
+	return meLayer, nil
+}
diff --git a/meframe/me_reboot_test.go b/meframe/me_reboot_test.go
new file mode 100644
index 0000000..8c16b7f
--- /dev/null
+++ b/meframe/me_reboot_test.go
@@ -0,0 +1,117 @@
+/*
+ * 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 meframe_test
+
+import (
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/opencord/omci-lib-go/meframe"
+	"github.com/stretchr/testify/assert"
+	"math/rand"
+	"testing"
+)
+
+func testRebootRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	params := me.ParamData{
+		EntityID: uint16(0),
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+	condition := uint8(rand.Int31n(3))     // [0, 3]
+
+	frame, omciErr := meframe.GenFrame(meInstance, RebootRequestType, meframe.TransactionID(tid),
+		meframe.RebootCondition(condition), meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, RebootRequestType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeRebootRequest)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*RebootRequest)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+	assert.Equal(t, condition, msgObj.RebootCondition)
+}
+
+func testRebootResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	params := me.ParamData{
+		EntityID: uint16(0),
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+	result := me.Results(rand.Int31n(7))   // [0, 6] Not all types will be tested
+
+	frame, omciErr := meframe.GenFrame(meInstance, RebootResponseType, meframe.TransactionID(tid),
+		meframe.Result(result), meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, RebootResponseType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeRebootResponse)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*RebootResponse)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+	assert.Equal(t, result, msgObj.Result)
+}
diff --git a/meframe/me_set.go b/meframe/me_set.go
new file mode 100644
index 0000000..af760a9
--- /dev/null
+++ b/meframe/me_set.go
@@ -0,0 +1,117 @@
+/*
+ * 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 meframe
+
+import (
+	"errors"
+	"fmt"
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+func SetRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	mask, err := checkAttributeMask(m, opt.attributeMask)
+	if err != nil {
+		return nil, err
+	}
+	mask, err = calculateAttributeMask(m, mask)
+	if err != nil {
+		return nil, err
+	}
+	meDefinition := m.GetManagedEntityDefinition()
+	attrDefs := meDefinition.GetAttributeDefinitions()
+	attrMap := m.GetAttributeValueMap()
+
+	// Get payload space available
+	maxPayload := maxPacketAvailable(m, opt)
+	payloadAvailable := int(maxPayload) - 2 // Less attribute mask
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+		// payloadAvailable -= 2				// Less length
+	}
+	meLayer := &SetRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		AttributeMask: 0,
+		Attributes:    make(me.AttributeValueMap),
+	}
+	for mask != 0 {
+		// Iterate down the attributes (Attribute 0 is the ManagedEntity ID)
+		var attrIndex uint
+		for attrIndex = 1; attrIndex <= 16; attrIndex++ {
+			// Is this attribute requested
+			if mask&(1<<(16-attrIndex)) != 0 {
+				// Get definitions since we need the name
+				attrDef, ok := attrDefs[attrIndex]
+				if !ok {
+					msg := fmt.Sprintf("Unexpected error, index %v not valued for ME %v",
+						attrIndex, meDefinition.GetName())
+					return nil, errors.New(msg)
+				}
+				var attrValue interface{}
+				attrValue, ok = attrMap[attrDef.Name]
+				if !ok {
+					msg := fmt.Sprintf("Unexpected error, attribute %v not provided in ME %v: %v",
+						attrDef.GetName(), meDefinition.GetName(), m)
+					return nil, errors.New(msg)
+				}
+				// Is space available?
+				if attrDef.Size <= payloadAvailable {
+					// Mark bit handled
+					mask &= ^attrDef.Mask
+					meLayer.AttributeMask |= attrDef.Mask
+					meLayer.Attributes[attrDef.Name] = attrValue
+					payloadAvailable -= attrDef.Size
+				} else {
+					// TODO: Should we set truncate?
+					msg := fmt.Sprintf("out-of-space. Cannot fit attribute %v into SetRequest message",
+						attrDef.GetName())
+					return nil, me.NewMessageTruncatedError(msg)
+				}
+			}
+		}
+	}
+	if meLayer.AttributeMask == 0 {
+		// TODO: Is a set request with no attributes valid?
+		return nil, errors.New("no attributes encoded for SetRequest")
+	}
+	return meLayer, nil
+}
+
+func SetResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	meLayer := &SetResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		Result: opt.result,
+	}
+	if meLayer.Result == me.AttributeFailure {
+		meLayer.UnsupportedAttributeMask = opt.unsupportedMask
+		meLayer.FailedAttributeMask = opt.attrExecutionMask
+	}
+	return meLayer, nil
+}
diff --git a/meframe/me_set_test.go b/meframe/me_set_test.go
new file mode 100644
index 0000000..33afb1a
--- /dev/null
+++ b/meframe/me_set_test.go
@@ -0,0 +1,175 @@
+/*
+ * 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 meframe_test
+
+import (
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/opencord/omci-lib-go/meframe"
+	"github.com/stretchr/testify/assert"
+	"math/rand"
+	"testing"
+)
+
+func testSetRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	params := me.ParamData{
+		EntityID:   uint16(0),
+		Attributes: make(me.AttributeValueMap, 0),
+	}
+	attrDefs := managedEntity.GetAttributeDefinitions()
+	tableAttrFound := false
+	for _, attrDef := range attrDefs {
+		if attrDef.Index == 0 {
+			continue // Skip entity ID, already specified
+		} else if attrDef.IsTableAttribute() {
+			tableAttrFound = true
+			continue // TODO: Skip table attributes for now
+		} else if attrDef.GetAccess().Contains(me.Write) {
+			params.Attributes[attrDef.GetName()] = pickAValue(attrDef)
+		}
+	}
+	if tableAttrFound && len(params.Attributes) == 0 {
+		// The only set attribute may have been a table and we do not have
+		// a test for that right now.
+		return
+	}
+	assert.NotEmpty(t, params.Attributes) // Need a parameter that is a table attribute
+	bitmask, attrErr := me.GetAttributesBitmap(attrDefs, getAttributeNameSet(params.Attributes))
+	assert.Nil(t, attrErr)
+
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+
+	frame, omciErr := meframe.GenFrame(meInstance, SetRequestType, meframe.TransactionID(tid),
+		meframe.AttributeMask(bitmask), meframe.FrameFormat(messageSet))
+	// some frames cannot fit all the attributes
+	if omciErr != nil {
+		if _, ok := omciErr.(*me.MessageTruncatedError); ok {
+			return
+		}
+	}
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, SetRequestType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeSetRequest)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*SetRequest)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+	assert.Equal(t, meInstance.GetAttributeValueMap(), msgObj.Attributes)
+}
+
+func testSetResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	params := me.ParamData{
+		EntityID: uint16(0),
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+	result := me.Results(rand.Int31n(10))  // [0, 9] Not all types will be tested
+
+	// Always pass a failure mask, but should only get encoded if result == ParameterError
+	var unsupportedMask uint16
+	var failedMask uint16
+	attrDefs := managedEntity.GetAttributeDefinitions()
+	for _, attrDef := range attrDefs {
+		if attrDef.Index == 0 {
+			continue // Skip entity ID, already specified
+
+		} else if attrDef.GetAccess().Contains(me.Write) {
+			// Random 10% chance this parameter unsupported and
+			// 10% it failed
+			switch rand.Int31n(5) {
+			case 0:
+				unsupportedMask |= attrDef.Mask
+			case 1:
+				failedMask |= attrDef.Mask
+			}
+		}
+	}
+	bitmask, attrErr := me.GetAttributesBitmap(attrDefs, getAttributeNameSet(params.Attributes))
+	assert.Nil(t, attrErr)
+
+	frame, omciErr := meframe.GenFrame(meInstance, SetResponseType,
+		meframe.TransactionID(tid), meframe.Result(result),
+		meframe.AttributeMask(bitmask), meframe.FrameFormat(messageSet),
+		meframe.AttributeExecutionMask(failedMask),
+		meframe.UnsupportedAttributeMask(unsupportedMask))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, SetResponseType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeSetResponse)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*SetResponse)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+	assert.Equal(t, result, msgObj.Result)
+
+	if result == me.AttributeFailure {
+		assert.Equal(t, failedMask, msgObj.FailedAttributeMask)
+		assert.Equal(t, unsupportedMask, msgObj.UnsupportedAttributeMask)
+	} else {
+		assert.Zero(t, msgObj.FailedAttributeMask)
+		assert.Zero(t, msgObj.UnsupportedAttributeMask)
+	}
+}
diff --git a/meframe/me_setable.go b/meframe/me_setable.go
new file mode 100644
index 0000000..07732c6
--- /dev/null
+++ b/meframe/me_setable.go
@@ -0,0 +1,82 @@
+/*
+ * 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 meframe
+
+import (
+	"errors"
+	"fmt"
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+func SetTableRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat != ExtendedIdent {
+		return nil, errors.New("set table message type only supported with Extended OMCI Messaging")
+	}
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	mask, err := checkAttributeMask(m, opt.attributeMask)
+	if err != nil {
+		return nil, err
+	}
+	// Common for all MEs
+	meLayer := &SetTableRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+	}
+	// Get payload space available
+	maxPayload := maxPacketAvailable(m, opt)
+
+	// TODO: Lots of work to do
+
+	fmt.Println(mask, maxPayload)
+	return meLayer, errors.New("todo: Not implemented")
+}
+
+func SetTableResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat != ExtendedIdent {
+		return nil, errors.New("set table message type only supported with Extended OMCI Message Set")
+	}
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	mask, err := checkAttributeMask(m, opt.attributeMask)
+	if err != nil {
+		return nil, err
+	}
+	// Common for all MEs
+	meLayer := &SetTableResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       true,
+		},
+	}
+	// Get payload space available
+	maxPayload := maxPacketAvailable(m, opt)
+
+	// TODO: Lots of work to do
+
+	fmt.Println(mask, maxPayload)
+	return meLayer, errors.New("todo: Not implemented")
+}
diff --git a/meframe/me_setable_test.go b/meframe/me_setable_test.go
new file mode 100644
index 0000000..3afe70a
--- /dev/null
+++ b/meframe/me_setable_test.go
@@ -0,0 +1,31 @@
+/*
+ * 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 meframe_test
+
+import (
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"testing"
+)
+
+func testSetTableRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	// TODO: Implement
+}
+
+func testSetTableResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	// TODO: Implement
+}
diff --git a/meframe/me_software.go b/meframe/me_software.go
new file mode 100644
index 0000000..6d6d3fb
--- /dev/null
+++ b/meframe/me_software.go
@@ -0,0 +1,262 @@
+/*
+ * 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 meframe
+
+import (
+	"errors"
+	"fmt"
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+func StartSoftwareDownloadRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	// Common for all MEs
+	meLayer := &StartSoftwareDownloadRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		WindowSize:           opt.software.WindowSize,
+		ImageSize:            opt.software.ImageSize,
+		NumberOfCircuitPacks: byte(len(opt.software.CircuitPacks)),
+		CircuitPacks:         opt.software.CircuitPacks,
+	}
+	// TODO: Add length check to insure we do not exceed maximum packet size
+	// payloadAvailable := int(maxPacketAvailable(m, opt))
+	payloadAvailable := 2
+	sizeNeeded := 1
+	if sizeNeeded > payloadAvailable {
+		// TODO: Should we set truncate?
+		msg := "out-of-space. Cannot fit Circuit Pack instances into Start Software Download Request message"
+		return nil, me.NewMessageTruncatedError(msg)
+	}
+	return meLayer, nil
+}
+
+func StartSoftwareDownloadResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	// Common for all MEs
+	meLayer := &StartSoftwareDownloadResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		WindowSize:        opt.software.WindowSize,
+		NumberOfInstances: byte(len(opt.software.CircuitPacks)),
+		MeResults:         opt.software.Results,
+	}
+	// TODO: Add length check to insure we do not exceed maximum packet size
+	// payloadAvailable := int(maxPacketAvailable(m, opt))
+	payloadAvailable := 2
+	sizeNeeded := 1
+	if sizeNeeded > payloadAvailable {
+		// TODO: Should we set truncate?
+		msg := "out-of-space. Cannot fit Results  into Start Software Download Response message"
+		return nil, me.NewMessageTruncatedError(msg)
+	}
+	return meLayer, nil
+}
+
+func DownloadSectionRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.software.Data == nil {
+		return nil, me.NewNonStatusError("Software image data missing")
+	}
+	// Common for all MEs
+	meLayer := &DownloadSectionRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		SectionNumber: opt.software.SectionNumber,
+		SectionData:   opt.software.Data,
+	}
+	return meLayer, nil
+}
+
+func DownloadSectionResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	// Common for all MEs
+	meLayer := &DownloadSectionResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		Result:        opt.result,
+		SectionNumber: opt.software.SectionNumber,
+	}
+	return meLayer, nil
+}
+
+func EndSoftwareDownloadRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	mask, err := checkAttributeMask(m, opt.attributeMask)
+	if err != nil {
+		return nil, err
+	}
+	// Common for all MEs
+	meLayer := &EndSoftwareDownloadRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+	}
+	// Get payload space available
+	maxPayload := maxPacketAvailable(m, opt)
+
+	// TODO: Lots of work to do
+
+	fmt.Println(mask, maxPayload)
+	return meLayer, errors.New("todo: Not implemented")
+}
+
+func EndSoftwareDownloadResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	mask, err := checkAttributeMask(m, opt.attributeMask)
+	if err != nil {
+		return nil, err
+	}
+	// Common for all MEs
+	meLayer := &EndSoftwareDownloadResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+	}
+	// Get payload space available
+	maxPayload := maxPacketAvailable(m, opt)
+
+	// TODO: Lots of work to do
+
+	fmt.Println(mask, maxPayload)
+	return meLayer, errors.New("todo: Not implemented")
+}
+
+func ActivateSoftwareRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	mask, err := checkAttributeMask(m, opt.attributeMask)
+	if err != nil {
+		return nil, err
+	}
+	// Common for all MEs
+	meLayer := &ActivateSoftwareRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+	}
+	// Get payload space available
+	maxPayload := maxPacketAvailable(m, opt)
+
+	// TODO: Lots of work to do
+
+	fmt.Println(mask, maxPayload)
+	return meLayer, errors.New("todo: Not implemented")
+}
+
+func ActivateSoftwareResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	mask, err := checkAttributeMask(m, opt.attributeMask)
+	if err != nil {
+		return nil, err
+	}
+	// Common for all MEs
+	meLayer := &ActivateSoftwareResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+	}
+	// Get payload space available
+	maxPayload := maxPacketAvailable(m, opt)
+
+	// TODO: Lots of work to do
+
+	fmt.Println(mask, maxPayload)
+	return meLayer, errors.New("todo: Not implemented")
+}
+
+func CommitSoftwareRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	mask, err := checkAttributeMask(m, opt.attributeMask)
+	if err != nil {
+		return nil, err
+	}
+	// Common for all MEs
+	meLayer := &CommitSoftwareRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+	}
+	// Get payload space available
+	maxPayload := maxPacketAvailable(m, opt)
+
+	// TODO: Lots of work to do
+
+	fmt.Println(mask, maxPayload)
+	return meLayer, errors.New("todo: Not implemented")
+}
+
+func CommitSoftwareResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	mask, err := checkAttributeMask(m, opt.attributeMask)
+	if err != nil {
+		return nil, err
+	}
+	// Common for all MEs
+	meLayer := &CommitSoftwareResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+	}
+	// Get payload space available
+	maxPayload := maxPacketAvailable(m, opt)
+
+	// TODO: Lots of work to do
+
+	fmt.Println(mask, maxPayload)
+	return meLayer, errors.New("todo: Not implemented")
+}
diff --git a/meframe/me_software_test.go b/meframe/me_software_test.go
new file mode 100644
index 0000000..7f0ae6e
--- /dev/null
+++ b/meframe/me_software_test.go
@@ -0,0 +1,224 @@
+/*
+ * 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 meframe_test
+
+import (
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/opencord/omci-lib-go/meframe"
+	"github.com/stretchr/testify/assert"
+	"math/rand"
+	"testing"
+)
+
+func testStartSoftwareDownloadRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	instance := uint16(0) // ONU-G
+	image := uint16(1)
+	params := me.ParamData{
+		EntityID: uint16((instance << 8) + image),
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+	options := meframe.SoftwareOptions{
+		WindowSize:   uint8(rand.Int31n(255)),                  // [0, 255]
+		ImageSize:    uint32(rand.Int31n(0x100000) + 0x100000), // [1 Meg, 2M-1]
+		CircuitPacks: []uint16{0},                              // [1 Meg, 2M-1]
+	}
+	frame, omciErr := meframe.GenFrame(meInstance, StartSoftwareDownloadRequestType,
+		meframe.TransactionID(tid), meframe.Software(options), meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, StartSoftwareDownloadRequestType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeStartSoftwareDownloadRequest)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*StartSoftwareDownloadRequest)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+	assert.Equal(t, options.ImageSize, msgObj.ImageSize)
+	assert.Equal(t, len(options.CircuitPacks), int(msgObj.NumberOfCircuitPacks))
+
+	for index, circuitPack := range options.CircuitPacks {
+		assert.Equal(t, circuitPack, msgObj.CircuitPacks[index])
+	}
+}
+
+func testStartSoftwareDownloadResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	// TODO: Implement
+}
+
+func testDownloadSectionRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	// TODO: In future, also support slot/multiple download formats
+	instance := uint16(0)
+	image := uint16(rand.Intn(1)) // Image 0 or 1 for this test
+	params := me.ParamData{
+		EntityID: (instance << 8) + image,
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+	var data []byte
+
+	if messageSet == ExtendedIdent {
+		data = make([]byte, MaxDownloadSectionExtendedLength)
+	} else {
+		data = make([]byte, MaxDownloadSectionLength)
+	}
+	for index := range data {
+		data[index] = byte(index & 0xFF)
+	}
+	options := meframe.SoftwareOptions{
+		SectionNumber: uint8(rand.Int31n(255)), // [0, 255]
+		Data:          data,
+	}
+	frame, omciErr := meframe.GenFrame(meInstance, DownloadSectionRequestType,
+		meframe.TransactionID(tid), meframe.Software(options), meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, DownloadSectionRequestType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeDownloadSectionRequest)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*DownloadSectionRequest)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+	assert.Equal(t, options.SectionNumber, msgObj.SectionNumber)
+	assert.NotNil(t, msgObj.SectionData)
+	assert.Equal(t, options.Data, msgObj.SectionData)
+}
+
+func testDownloadSectionResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	instance := uint16(0)
+	image := uint16(rand.Intn(1)) // Image 0 or 1 for this test
+	params := me.ParamData{
+		EntityID: (instance << 8) + image,
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+	result := me.Results(rand.Int31n(7))   // [0, 6] Not all types will be tested
+	swOptions := meframe.SoftwareOptions{
+		SectionNumber: uint8(rand.Int31n(255)), // [0, 255]
+	}
+	var frame []byte
+	frame, omciErr := meframe.GenFrame(meInstance, DownloadSectionResponseType, meframe.TransactionID(tid),
+		meframe.Result(result), meframe.FrameFormat(messageSet), meframe.Software(swOptions))
+
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, DownloadSectionResponseType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeDownloadSectionResponse)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*DownloadSectionResponse)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+	assert.Equal(t, result, msgObj.Result)
+	assert.Equal(t, swOptions.SectionNumber, msgObj.SectionNumber)
+}
+
+func testEndSoftwareDownloadRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	// TODO: Implement
+}
+
+func testEndSoftwareDownloadResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	// TODO: Implement
+}
+
+func testActivateSoftwareRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	// TODO: Implement
+}
+
+func testActivateSoftwareResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	// TODO: Implement
+}
+
+func testCommitSoftwareRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	// TODO: Implement
+}
+
+func testCommitSoftwareResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	// TODO: Implement
+}
diff --git a/meframe/me_synctime.go b/meframe/me_synctime.go
new file mode 100644
index 0000000..4773bc8
--- /dev/null
+++ b/meframe/me_synctime.go
@@ -0,0 +1,68 @@
+/*
+ * 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 meframe
+
+import (
+	"errors"
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"time"
+)
+
+func SynchronizeTimeRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	// Common for all MEs
+	meLayer := &SynchronizeTimeRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+	}
+	// Decode payload option. If nil, no timestamp provided
+	if timestamp, ok := opt.payload.(int64); ok {
+		tm := time.Unix(timestamp, 0)
+		meLayer.Year = uint16(tm.UTC().Year())
+		meLayer.Month = uint8(tm.UTC().Month())
+		meLayer.Day = uint8(tm.UTC().Day())
+		meLayer.Hour = uint8(tm.UTC().Hour())
+		meLayer.Minute = uint8(tm.UTC().Minute())
+		meLayer.Second = uint8(tm.UTC().Second())
+	}
+	return meLayer, nil
+}
+
+func SynchronizeTimeResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+	if opt.frameFormat == ExtendedIdent {
+		return nil, errors.New("extended message set for this message type is not supported")
+	}
+	// Common for all MEs
+	meLayer := &SynchronizeTimeResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    m.GetClassID(),
+			EntityInstance: m.GetEntityID(),
+			Extended:       opt.frameFormat == ExtendedIdent,
+		},
+		Result:         opt.result,
+		SuccessResults: opt.mode,
+	}
+	return meLayer, nil
+}
diff --git a/meframe/me_synctime_test.go b/meframe/me_synctime_test.go
new file mode 100644
index 0000000..4ebe6d2
--- /dev/null
+++ b/meframe/me_synctime_test.go
@@ -0,0 +1,132 @@
+/*
+ * 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 meframe_test
+
+import (
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/opencord/omci-lib-go/meframe"
+	"github.com/stretchr/testify/assert"
+	"math/rand"
+	"testing"
+	"time"
+)
+
+func testSynchronizeTimeRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	params := me.ParamData{
+		EntityID: uint16(0),
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+	tm := time.Now().UTC()
+	tmUnix := tm.Unix()
+
+	frame, omciErr := meframe.GenFrame(meInstance, SynchronizeTimeRequestType, meframe.TransactionID(tid),
+		meframe.Payload(tmUnix), meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, SynchronizeTimeRequestType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeSynchronizeTimeRequest)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*SynchronizeTimeRequest)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+
+	assert.Equal(t, uint16(tm.Year()), msgObj.Year)
+	assert.Equal(t, uint8(tm.Month()), msgObj.Month)
+	assert.Equal(t, uint8(tm.Day()), msgObj.Day)
+	assert.Equal(t, uint8(tm.Hour()), msgObj.Hour)
+	assert.Equal(t, uint8(tm.Minute()), msgObj.Minute)
+	assert.Equal(t, uint8(tm.Second()), msgObj.Second)
+}
+
+func testSynchronizeTimeResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	params := me.ParamData{
+		EntityID: uint16(0),
+	}
+	// Create the managed instance
+	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+	result := me.Results(rand.Int31n(7))   // [0, 6] Not all types will be tested
+	successResult := uint8(rand.Int31n(2)) // [0, 1]
+
+	var frame []byte
+	frame, omciErr := meframe.GenFrame(meInstance, SynchronizeTimeResponseType, meframe.TransactionID(tid),
+		meframe.Result(result), meframe.SuccessResult(successResult), meframe.FrameFormat(messageSet))
+	assert.NotNil(t, frame)
+	assert.NotZero(t, len(frame))
+	assert.Nil(t, omciErr)
+
+	///////////////////////////////////////////////////////////////////
+	// Now decode and compare
+	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciObj, omciOk := omciLayer.(*OMCI)
+	assert.NotNil(t, omciObj)
+	assert.True(t, omciOk)
+	assert.Equal(t, tid, omciObj.TransactionID)
+	assert.Equal(t, SynchronizeTimeResponseType, omciObj.MessageType)
+	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
+
+	msgLayer := packet.Layer(LayerTypeSynchronizeTimeResponse)
+	assert.NotNil(t, msgLayer)
+
+	msgObj, msgOk := msgLayer.(*SynchronizeTimeResponse)
+	assert.NotNil(t, msgObj)
+	assert.True(t, msgOk)
+
+	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+	assert.Equal(t, result, msgObj.Result)
+	if result == me.Success {
+		assert.Equal(t, successResult, msgObj.SuccessResults)
+	} else {
+		assert.Zero(t, msgObj.SuccessResults)
+	}
+}
diff --git a/meframe/me_test.go b/meframe/me_test.go
new file mode 100644
index 0000000..45ddd15
--- /dev/null
+++ b/meframe/me_test.go
@@ -0,0 +1,93 @@
+/*
+ * 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 meframe
+
+//func TestRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+//	if opt.frameFormat == ExtendedIdent {
+//		return nil, errors.New("Extended message set for this message type is not supported")
+//	}
+//	mask, err := checkAttributeMask(m, opt.attributeMask)
+//	if err != nil {
+//		return nil, err
+//	}
+//	// Common for all MEs
+//	meLayer := &TestRequest{
+//		MeBasePacket: MeBasePacket{
+//			EntityClass:    m.GetClassID(),
+//			EntityInstance: m.GetEntityID(),
+//			Extended:       opt.frameFormat == ExtendedIdent,
+//		},
+//	}
+//	// Get payload space available
+//	maxPayload := maxPacketAvailable(m, opt)
+//
+//	// TODO: Lots of work to do
+//
+//	fmt.Println(mask, maxPayload)
+//	return meLayer, errors.New("todo: Not implemented")
+//}
+
+//func TestResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+//	if opt.frameFormat == ExtendedIdent {
+//		return nil, errors.New("Extended message set for this message type is not supported")
+//	}
+//	mask, err := checkAttributeMask(m, opt.attributeMask)
+//	if err != nil {
+//		return nil, err
+//	}
+//	// Common for all MEs
+//	meLayer := &TestResponse{
+//		MeBasePacket: MeBasePacket{
+//			EntityClass:    m.GetClassID(),
+//			EntityInstance: m.GetEntityID(),
+//			Extended:       opt.frameFormat == ExtendedIdent,
+//		},
+//	}
+//	// Get payload space available
+//	maxPayload := maxPacketAvailable(m, opt)
+//
+//	// TODO: Lots of work to do
+//
+//	fmt.Println(mask, maxPayload)
+//	return meLayer, errors.New("todo: Not implemented")
+//}
+
+//func TestResultFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
+//	if opt.frameFormat == ExtendedIdent {
+//		return nil, errors.New("Extended message set for this message type is not supported")
+//	}
+//	mask, err := checkAttributeMask(m, opt.attributeMask)
+//	if err != nil {
+//		return nil, err
+//	}
+//	// Common for all MEs
+//	meLayer := &TestResultNotification{
+//		MeBasePacket: MeBasePacket{
+//			EntityClass:    m.GetClassID(),
+//			EntityInstance: m.GetEntityID(),
+//			Extended:       opt.frameFormat == ExtendedIdent,
+//		},
+//	}
+//	// Get payload space available
+//	maxPayload := maxPacketAvailable(m, opt)
+//
+//	// TODO: Lots of work to do
+//
+//	fmt.Println(mask, maxPayload)
+//	return meLayer, errors.New("todo: Not implemented")
+//}
diff --git a/meframe/me_test_test.go b/meframe/me_test_test.go
new file mode 100644
index 0000000..a68c7f3
--- /dev/null
+++ b/meframe/me_test_test.go
@@ -0,0 +1,35 @@
+/*
+ * 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 meframe_test
+
+import (
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"testing"
+)
+
+func testTestRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	// TODO: Implement
+}
+
+func testTestResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	// TODO: Implement
+}
+
+func testTestResultTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
+	// TODO: Implement
+}
diff --git a/meframe/meframe.go b/meframe/meframe.go
new file mode 100644
index 0000000..a6b384b
--- /dev/null
+++ b/meframe/meframe.go
@@ -0,0 +1,415 @@
+/*
+ * 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 meframe
+
+import (
+	"errors"
+	"fmt"
+	"github.com/deckarep/golang-set"
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+var encoderMap map[MessageType]func(*me.ManagedEntity, options) (gopacket.SerializableLayer, error)
+
+func init() {
+	encoderMap = make(map[MessageType]func(*me.ManagedEntity, options) (gopacket.SerializableLayer, error))
+
+	encoderMap[CreateRequestType] = CreateRequestFrame
+	encoderMap[DeleteRequestType] = DeleteRequestFrame
+	encoderMap[SetRequestType] = SetRequestFrame
+	encoderMap[GetRequestType] = GetRequestFrame
+	encoderMap[GetAllAlarmsRequestType] = GetAllAlarmsRequestFrame
+	encoderMap[GetAllAlarmsNextRequestType] = GetAllAlarmsNextRequestFrame
+	encoderMap[MibUploadRequestType] = MibUploadRequestFrame
+	encoderMap[MibUploadNextRequestType] = MibUploadNextRequestFrame
+	encoderMap[MibResetRequestType] = MibResetRequestFrame
+	//encoderMap[TestRequestType] = TestRequestFrame
+	encoderMap[StartSoftwareDownloadRequestType] = StartSoftwareDownloadRequestFrame
+	encoderMap[DownloadSectionRequestType] = DownloadSectionRequestFrame
+	encoderMap[EndSoftwareDownloadRequestType] = EndSoftwareDownloadRequestFrame
+	encoderMap[ActivateSoftwareRequestType] = ActivateSoftwareRequestFrame
+	encoderMap[CommitSoftwareRequestType] = CommitSoftwareRequestFrame
+	encoderMap[SynchronizeTimeRequestType] = SynchronizeTimeRequestFrame
+	encoderMap[RebootRequestType] = RebootRequestFrame
+	encoderMap[GetNextRequestType] = GetNextRequestFrame
+	encoderMap[GetCurrentDataRequestType] = GetCurrentDataRequestFrame
+	encoderMap[SetTableRequestType] = SetTableRequestFrame
+	encoderMap[CreateResponseType] = CreateResponseFrame
+	encoderMap[DeleteResponseType] = DeleteResponseFrame
+	encoderMap[SetResponseType] = SetResponseFrame
+	encoderMap[GetResponseType] = GetResponseFrame
+	encoderMap[GetAllAlarmsResponseType] = GetAllAlarmsResponseFrame
+	encoderMap[GetAllAlarmsNextResponseType] = GetAllAlarmsNextResponseFrame
+	encoderMap[MibUploadResponseType] = MibUploadResponseFrame
+	encoderMap[MibUploadNextResponseType] = MibUploadNextResponseFrame
+	encoderMap[MibResetResponseType] = MibResetResponseFrame
+	//encoderMap[TestResponseType] = TestResponseFrame
+	encoderMap[StartSoftwareDownloadResponseType] = StartSoftwareDownloadResponseFrame
+	encoderMap[DownloadSectionResponseType] = DownloadSectionResponseFrame
+	encoderMap[EndSoftwareDownloadResponseType] = EndSoftwareDownloadResponseFrame
+	encoderMap[ActivateSoftwareResponseType] = ActivateSoftwareResponseFrame
+	encoderMap[CommitSoftwareResponseType] = CommitSoftwareResponseFrame
+	encoderMap[SynchronizeTimeResponseType] = SynchronizeTimeResponseFrame
+	encoderMap[RebootResponseType] = RebootResponseFrame
+	encoderMap[GetNextResponseType] = GetNextResponseFrame
+	encoderMap[GetCurrentDataResponseType] = GetCurrentDataResponseFrame
+	encoderMap[SetTableResponseType] = SetTableResponseFrame
+	encoderMap[AlarmNotificationType] = AlarmNotificationFrame
+	encoderMap[AttributeValueChangeType] = AttributeValueChangeFrame
+	//encoderMap[TestResultType] = TestResultFrame
+}
+
+type options struct {
+	frameFormat               DeviceIdent
+	failIfTruncated           bool
+	attributeMask             uint16
+	result                    me.Results      // Common for many responses
+	attrExecutionMask         uint16          // Create Response Only if results == 3 or Set Response only if results == 0
+	unsupportedMask           uint16          // Set Response only if results == 9
+	sequenceNumberCountOrSize uint16          // For get-next request frames and for frames that return number of commands or length
+	transactionID             uint16          // OMCI TID
+	mode                      uint8           // Get All Alarms retrieval mode
+	alarm                     AlarmOptions    // Alarm related frames
+	software                  SoftwareOptions // Software image related frames
+	payload                   interface{}     // ME or list of MEs, alarm bitmap, timestamp, ...
+	addDefaults               bool            // Add missing SetByCreate attributes for Create Requests
+}
+
+var defaultFrameOptions = options{
+	frameFormat:               BaselineIdent,
+	failIfTruncated:           false,
+	attributeMask:             0xFFFF,
+	result:                    me.Success,
+	attrExecutionMask:         0,
+	unsupportedMask:           0,
+	sequenceNumberCountOrSize: 0,
+	transactionID:             0,
+	mode:                      0,
+	software:                  defaultSoftwareOptions,
+	alarm:                     defaultAlarmOptions,
+	payload:                   nil,
+	addDefaults:               false,
+}
+
+// FrameOption sets options such as frame format, etc.
+type FrameOption func(*options)
+
+// FrameFormat determines determines the OMCI message format used on the fiber.
+// The default value is BaselineIdent
+func FrameFormat(ff DeviceIdent) FrameOption {
+	return func(o *options) {
+		o.frameFormat = ff
+	}
+}
+
+// FailIfTruncated determines whether a request to encode a frame that does
+// not have enough room for all requested options should fail and return an
+// error.
+//
+// If set to 'false', the behaviour depends on the message type/operation
+// requested. The table below provides more information:
+//
+//   Request Type	Behavour
+//	 ------------------------------------------------------------------------
+//	 CreateRequest  A single CreateRequest struct is always returned as the
+//                  CreateRequest message does not have an attributes Mask
+//                  field and a Baseline OMCI message is large enough to
+//                  support all Set-By-Create attributes.
+//
+//   GetResponse	If multiple OMCI response frames are needed to return
+//					all requested attributes, only the attributes that can
+//					fit will be returned and the FailedAttributeMask field
+//					set to the attributes that could not be returned
+//
+//					If this is an ME with an attribute that is a table, the
+//					first GetResponse struct will return the size of the
+//					attribute and the following GetNextResponse structs will
+//					contain the attribute data. The ONU application is
+//					responsible for stashing these extra struct(s) away in
+//					anticipation of possible GetNext Requests occurring for
+//					the attribute.  See the discussion on Table attributes
+//					in the GetResponse section of ITU G.988 for more
+//					information.
+//
+// If set to 'true', no struct(s) are returned and an error is provided.
+//
+// The default value is 'false'
+func FailIfTruncated(f bool) FrameOption {
+	return func(o *options) {
+		o.failIfTruncated = f
+	}
+}
+
+// attributeMask determines the attributes to encode into the frame.
+// The default value is 0xFFFF which specifies all available attributes
+// in the frame
+func AttributeMask(m uint16) FrameOption {
+	return func(o *options) {
+		o.attributeMask = m
+	}
+}
+
+// AttributeExecutionMask is used by the Create and Set Response frames to indicate
+// attributes that failed to be created/set.
+func AttributeExecutionMask(m uint16) FrameOption {
+	return func(o *options) {
+		o.attrExecutionMask = m
+	}
+}
+
+// UnsupportedAttributeMask is used by the Set Response frames to indicate
+// attributes are not supported on this ONU
+func UnsupportedAttributeMask(m uint16) FrameOption {
+	return func(o *options) {
+		o.unsupportedMask = m
+	}
+}
+
+// Result is used to set returned results in responses
+// that have that field
+func Result(r me.Results) FrameOption {
+	return func(o *options) {
+		o.result = r
+	}
+}
+
+// SequenceNumberCountOrSize is used by the GetNext and MibUploadGetNext request frames and for
+// frames that return number of commands or length such as Get (table attribute) or
+// MibUpload/GetAllAlarms/...
+func SequenceNumberCountOrSize(m uint16) FrameOption {
+	return func(o *options) {
+		o.sequenceNumberCountOrSize = m
+	}
+}
+
+// TransactionID is to specify the TID in the OMCI header. The default is
+// zero which requires the caller to set it to the appropriate value if this
+// is not an autonomous ONU notification frame
+func TransactionID(tid uint16) FrameOption {
+	return func(o *options) {
+		o.transactionID = tid
+	}
+}
+
+// RetrievalMode is to specify the the Alarm Retrieval Mode in a GetAllAlarms Request
+func RetrievalMode(m uint8) FrameOption {
+	return func(o *options) {
+		o.mode = m
+	}
+}
+
+// SuccessResult is to specify the the SuccessResult for a SynchronizeTime Response
+func SuccessResult(m uint8) FrameOption {
+	return func(o *options) {
+		o.mode = m
+	}
+}
+
+// RebootCondition is to specify the the Reboot Condition for a ONU Reboot request
+func RebootCondition(m uint8) FrameOption {
+	return func(o *options) {
+		o.mode = m
+	}
+}
+
+// Alarm is used to specify a collection of options related to Alarm notifications
+func Alarm(ao AlarmOptions) FrameOption {
+	return func(o *options) {
+		o.alarm = ao
+	}
+}
+
+// Software is used to specify a collection of options related to Software image
+// manipulation
+func Software(so SoftwareOptions) FrameOption {
+	return func(o *options) {
+		o.software = so
+	}
+}
+
+// Payload is used to specify ME payload options that are not simple types. This
+// include the ME (list of MEs) to encode into a GetNextMibUpload response, the
+// alarm bitmap for alarm relates responses/notifications, alarm bitmaps, and
+// for specifying the download section data when performing Software Download.
+func Payload(p interface{}) FrameOption {
+	return func(o *options) {
+		o.payload = p
+	}
+}
+
+// AddDefaults is used to specify that if a SetByCreate attribute is not
+// specified in the list of attributes for a Create Request, use the attribute
+// defined default
+func AddDefaults(add bool) FrameOption {
+	return func(o *options) {
+		o.addDefaults = add
+	}
+}
+
+// Alarm related frames have a wide variety of settable values. Placing them
+// in a separate struct is mainly to keep the base options simple
+type AlarmOptions struct {
+	AlarmClassID  me.ClassID
+	AlarmInstance uint16
+	AlarmBitmap   []byte // Should be up to 58 octets
+}
+
+var defaultAlarmOptions = AlarmOptions{
+	AlarmClassID:  0,
+	AlarmInstance: 0,
+	AlarmBitmap:   nil,
+}
+
+// Software related frames have a wide variety of settable values. Placing them
+// in a separate struct is mainly to keep the base options simple
+type SoftwareOptions struct {
+	WindowSize    uint8 // Window size - 1
+	SectionNumber uint8 // [0..Window size - 1]
+	ImageSize     uint32
+	CircuitPacks  []uint16 // slot (upper 8 bits) and instance (lower 8 bits)
+	Results       []DownloadResults
+	Data          []byte
+}
+
+var defaultSoftwareOptions = SoftwareOptions{
+	WindowSize:    0,
+	SectionNumber: 0,
+	ImageSize:     0,
+	CircuitPacks:  nil,
+	Results:       nil,
+	Data:          nil,
+}
+
+// EncodeFrame will encode the Managed Entity specific protocol struct and an
+// OMCILayer struct. This struct can be provided to the gopacket.SerializeLayers()
+// function to be serialized into a buffer for transmission.
+func EncodeFrame(m *me.ManagedEntity, messageType MessageType, opt ...FrameOption) (*OMCI, gopacket.SerializableLayer, error) {
+	// Check for message type support
+	msgType := me.MsgType(messageType & me.MsgTypeMask)
+	meDefinition := m.GetManagedEntityDefinition()
+
+	if !me.SupportsMsgType(meDefinition, msgType) {
+		msg := fmt.Sprintf("managed entity %v does not support %v Message-Type",
+			meDefinition.GetName(), msgType)
+		return nil, nil, errors.New(msg)
+	}
+	// Decode options
+	opts := defaultFrameOptions
+	for _, o := range opt {
+		o(&opts)
+	}
+	// TODO: If AttributesMask option passed in, check for deprecated options. Allow encoding option
+	//       that will ignore deprecated option.   Add additional in the get and set meframe_test,go
+	//       test functions to test this. Also have it test attribute name(s) to see if the attribute
+	//       is deprecated.  The OMCI-Parser now supports detection of deprecated attributes and
+	//       provides that to the code-generator (and currently available in generated golang code).
+	// Note: Transaction ID should be set before frame serialization
+	omci := &OMCI{
+		TransactionID:    opts.transactionID,
+		MessageType:      messageType,
+		DeviceIdentifier: opts.frameFormat,
+	}
+	var meInfo gopacket.SerializableLayer
+	var err error
+
+	if encoder, ok := encoderMap[messageType]; ok {
+		meInfo, err = encoder(m, opts)
+	} else {
+		err = fmt.Errorf("message-type: %v/%#x is not supported", messageType, messageType)
+	}
+	if err != nil {
+		return nil, nil, err
+	}
+	return omci, meInfo, err
+}
+
+// For most all create methods below, error checking for valid masks, attribute
+// values, and other fields is left to when the frame is actually serialized.
+
+func checkAttributeMask(m *me.ManagedEntity, mask uint16) (uint16, error) {
+	if mask == defaultFrameOptions.attributeMask {
+		// Scale back to just what is allowed
+		return m.GetAllowedAttributeMask(), nil
+	}
+	if mask&m.GetManagedEntityDefinition().GetAllowedAttributeMask() != mask {
+		return 0, errors.New("invalid attribute mask")
+	}
+	return mask & m.GetManagedEntityDefinition().GetAllowedAttributeMask(), nil
+}
+
+// return the maximum space that can be used by attributes
+func maxPacketAvailable(m *me.ManagedEntity, opt options) uint {
+	if opt.frameFormat == BaselineIdent {
+		// OMCI Header          - 4 octets
+		// Class ID/Instance ID - 4 octets
+		// Length field			- 4 octets
+		// MIC                  - 4 octets
+		return MaxBaselineLength - 16
+	}
+	// OMCI Header          - 4 octets
+	// Class ID/Instance ID - 4 octets
+	// Length field			- 2 octets
+	// MIC                  - 4 octets
+	return MaxExtendedLength - 14
+}
+
+func calculateAttributeMask(m *me.ManagedEntity, requestedMask uint16) (uint16, error) {
+	attrDefs := m.GetAttributeDefinitions()
+	var entityIDName string
+	if entry, ok := attrDefs[0]; ok {
+		entityIDName = entry.GetName()
+	} else {
+		panic("unexpected error") // All attribute definition maps have an entity ID
+	}
+	attributeNames := make([]interface{}, 0)
+	for attrName := range m.GetAttributeValueMap() {
+		if attrName == entityIDName {
+			continue // No mask for EntityID
+		}
+		attributeNames = append(attributeNames, attrName)
+	}
+	calculatedMask, err := me.GetAttributesBitmap(attrDefs, mapset.NewSetWith(attributeNames...))
+
+	if err != nil {
+		return 0, err
+	}
+	return calculatedMask & requestedMask, nil
+}
+
+// GenFrame is a helper function to make tests a little easier to read.
+// For a real application, use the .../omci/generated/class.go 'New'
+// functions to create your Managed Entity and then use it to call the
+// EncodeFrame method.
+func GenFrame(meInstance *me.ManagedEntity, messageType MessageType, options ...FrameOption) ([]byte, error) {
+	omciLayer, msgLayer, err := EncodeFrame(meInstance, messageType, options...)
+	if err != nil {
+		return nil, err
+	}
+	// Serialize the frame and send it
+	var serializeOptions gopacket.SerializeOptions
+	serializeOptions.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err = gopacket.SerializeLayers(buffer, serializeOptions, omciLayer, msgLayer)
+	if err != nil {
+		return nil, err
+	}
+	return buffer.Bytes(), nil
+}
diff --git a/meframe/meframe_test.go b/meframe/meframe_test.go
new file mode 100644
index 0000000..9ebacb1
--- /dev/null
+++ b/meframe/meframe_test.go
@@ -0,0 +1,439 @@
+/*
+ * 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 meframe_test
+
+import (
+	mapset "github.com/deckarep/golang-set"
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/opencord/omci-lib-go/meframe"
+	"github.com/stretchr/testify/assert"
+	"math/rand"
+	"testing"
+)
+
+var messageTypeTestFuncs map[MessageType]func(*testing.T, *me.ManagedEntity, DeviceIdent)
+
+var allMessageTypes = [...]MessageType{
+	CreateRequestType,
+	CreateResponseType,
+	DeleteRequestType,
+	DeleteResponseType,
+	SetRequestType,
+	SetResponseType,
+	GetRequestType,
+	GetResponseType,
+	GetAllAlarmsRequestType,
+	GetAllAlarmsResponseType,
+	GetAllAlarmsNextRequestType,
+	GetAllAlarmsNextResponseType,
+	MibUploadRequestType,
+	MibUploadResponseType,
+	MibUploadNextRequestType,
+	MibUploadNextResponseType,
+	MibResetRequestType,
+	MibResetResponseType,
+	TestRequestType,
+	TestResponseType,
+	StartSoftwareDownloadRequestType,
+	StartSoftwareDownloadResponseType,
+	DownloadSectionRequestType,
+	DownloadSectionResponseType,
+	EndSoftwareDownloadRequestType,
+	EndSoftwareDownloadResponseType,
+	ActivateSoftwareRequestType,
+	ActivateSoftwareResponseType,
+	CommitSoftwareRequestType,
+	CommitSoftwareResponseType,
+	SynchronizeTimeRequestType,
+	SynchronizeTimeResponseType,
+	RebootRequestType,
+	RebootResponseType,
+	GetNextRequestType,
+	GetNextResponseType,
+	GetCurrentDataRequestType,
+	GetCurrentDataResponseType,
+	SetTableRequestType,
+	SetTableResponseType,
+	// Autonomous ONU messages
+	AlarmNotificationType,
+	AttributeValueChangeType,
+	TestResultType,
+}
+
+var allExtendedMessageTypes = [...]MessageType{
+	GetRequestType,
+	GetResponseType,
+}
+
+func init() {
+	messageTypeTestFuncs = make(map[MessageType]func(*testing.T, *me.ManagedEntity, DeviceIdent), 0)
+
+	messageTypeTestFuncs[CreateRequestType] = testCreateRequestTypeMeFrame
+	messageTypeTestFuncs[CreateResponseType] = testCreateResponseTypeMeFrame
+	messageTypeTestFuncs[DeleteRequestType] = testDeleteRequestTypeMeFrame
+	messageTypeTestFuncs[DeleteResponseType] = testDeleteResponseTypeMeFrame
+	messageTypeTestFuncs[SetRequestType] = testSetRequestTypeMeFrame
+	messageTypeTestFuncs[SetResponseType] = testSetResponseTypeMeFrame
+	messageTypeTestFuncs[GetRequestType] = testGetRequestTypeMeFrame
+	messageTypeTestFuncs[GetResponseType] = testGetResponseTypeMeFrame
+	messageTypeTestFuncs[GetAllAlarmsRequestType] = testGetAllAlarmsRequestTypeMeFrame
+	messageTypeTestFuncs[GetAllAlarmsResponseType] = testGetAllAlarmsResponseTypeMeFrame
+	messageTypeTestFuncs[GetAllAlarmsNextRequestType] = testGetAllAlarmsNextRequestTypeMeFrame
+	messageTypeTestFuncs[GetAllAlarmsNextResponseType] = testGetAllAlarmsNextResponseTypeMeFrame
+	messageTypeTestFuncs[MibUploadRequestType] = testMibUploadRequestTypeMeFrame
+	messageTypeTestFuncs[MibUploadResponseType] = testMibUploadResponseTypeMeFrame
+	messageTypeTestFuncs[MibUploadNextRequestType] = testMibUploadNextRequestTypeMeFrame
+	messageTypeTestFuncs[MibUploadNextResponseType] = testMibUploadNextResponseTypeMeFrame
+	messageTypeTestFuncs[MibResetRequestType] = testMibResetRequestTypeMeFrame
+	messageTypeTestFuncs[MibResetResponseType] = testMibResetResponseTypeMeFrame
+	messageTypeTestFuncs[TestRequestType] = testTestRequestTypeMeFrame
+	messageTypeTestFuncs[TestResponseType] = testTestResponseTypeMeFrame
+
+	// For Download section, AR=0 if not response expected, AR=1 if response expected (last section of a window)4
+	messageTypeTestFuncs[StartSoftwareDownloadRequestType] = testStartSoftwareDownloadRequestTypeMeFrame
+	messageTypeTestFuncs[StartSoftwareDownloadResponseType] = testStartSoftwareDownloadResponseTypeMeFrame
+	messageTypeTestFuncs[DownloadSectionRequestType] = testDownloadSectionRequestTypeMeFrame
+	messageTypeTestFuncs[DownloadSectionResponseType] = testDownloadSectionResponseTypeMeFrame
+	messageTypeTestFuncs[EndSoftwareDownloadRequestType] = testEndSoftwareDownloadRequestTypeMeFrame
+	messageTypeTestFuncs[EndSoftwareDownloadResponseType] = testEndSoftwareDownloadResponseTypeMeFrame
+	messageTypeTestFuncs[ActivateSoftwareRequestType] = testActivateSoftwareRequestTypeMeFrame
+	messageTypeTestFuncs[ActivateSoftwareResponseType] = testActivateSoftwareResponseTypeMeFrame
+	messageTypeTestFuncs[CommitSoftwareRequestType] = testCommitSoftwareRequestTypeMeFrame
+	messageTypeTestFuncs[CommitSoftwareResponseType] = testCommitSoftwareResponseTypeMeFrame
+	messageTypeTestFuncs[SynchronizeTimeRequestType] = testSynchronizeTimeRequestTypeMeFrame
+	messageTypeTestFuncs[SynchronizeTimeResponseType] = testSynchronizeTimeResponseTypeMeFrame
+	messageTypeTestFuncs[RebootRequestType] = testRebootRequestTypeMeFrame
+	messageTypeTestFuncs[RebootResponseType] = testRebootResponseTypeMeFrame
+	messageTypeTestFuncs[GetNextRequestType] = testGetNextRequestTypeMeFrame
+	messageTypeTestFuncs[GetNextResponseType] = testGetNextResponseTypeMeFrame
+	messageTypeTestFuncs[GetCurrentDataRequestType] = testGetCurrentDataRequestTypeMeFrame
+	messageTypeTestFuncs[GetCurrentDataResponseType] = testGetCurrentDataResponseTypeMeFrame
+	messageTypeTestFuncs[SetTableRequestType] = testSetTableRequestTypeMeFrame
+	messageTypeTestFuncs[SetTableResponseType] = testSetTableResponseTypeMeFrame
+	messageTypeTestFuncs[AlarmNotificationType] = testAlarmNotificationTypeMeFrame
+	messageTypeTestFuncs[AttributeValueChangeType] = testAttributeValueChangeTypeMeFrame
+	messageTypeTestFuncs[TestResultType] = testTestResultTypeMeFrame
+
+	// Supported Extended message set types here
+	messageTypeTestFuncs[GetRequestType+ExtendedTypeDecodeOffset] = testGetRequestTypeMeFrame
+	messageTypeTestFuncs[GetResponseType+ExtendedTypeDecodeOffset] = testGetResponseTypeMeFrame
+
+	// For Download section, AR=0 if not response expected, AR=1 if response expected (last section of a window)
+	messageTypeTestFuncs[DownloadSectionRequestType+ExtendedTypeDecodeOffset] = testDownloadSectionRequestTypeMeFrame
+	// TODO: messageTypeTestFuncs[DownloadSectionRequestWithResponseType+ExtendedTypeDecodeOffset] = testDownloadSectionLastRequestTypeMeFrame
+	messageTypeTestFuncs[DownloadSectionResponseType+ExtendedTypeDecodeOffset] = testDownloadSectionResponseTypeMeFrame
+
+	messageTypeTestFuncs[AlarmNotificationType+ExtendedTypeDecodeOffset] = testAlarmNotificationTypeMeFrame
+	messageTypeTestFuncs[AttributeValueChangeType+ExtendedTypeDecodeOffset] = testAttributeValueChangeTypeMeFrame
+	messageTypeTestFuncs[TestResultType+ExtendedTypeDecodeOffset] = testTestResultTypeMeFrame
+}
+
+func getMEsThatSupportAMessageType(messageType MessageType) []*me.ManagedEntity {
+	msgType := me.MsgType(byte(messageType) & me.MsgTypeMask)
+
+	entities := make([]*me.ManagedEntity, 0)
+	for _, classID := range me.GetSupportedClassIDs() {
+		if managedEntity, err := me.LoadManagedEntityDefinition(classID); err.StatusCode() == me.Success {
+			supportedTypes := managedEntity.GetManagedEntityDefinition().GetMessageTypes()
+			if supportedTypes.Contains(msgType) {
+				entities = append(entities, managedEntity)
+			}
+		}
+	}
+	return entities
+}
+
+func TestFrameFormatNotYetSupported(t *testing.T) {
+	// We do not yet support a few message types for the extended frame formats.
+	// As we do, add appropriate tests and change this to one that is not supported
+	// Until all are supported
+
+	params := me.ParamData{
+		Attributes: me.AttributeValueMap{"MibDataSync": 0},
+	}
+	managedEntity, omciErr := me.NewOnuData(params)
+	assert.NotNil(t, omciErr)
+	assert.Equal(t, omciErr.StatusCode(), me.Success)
+
+	buffer, err := meframe.GenFrame(managedEntity, SetRequestType, meframe.FrameFormat(ExtendedIdent), meframe.TransactionID(1))
+	assert.Nil(t, buffer)
+	assert.NotNil(t, err)
+}
+
+// TODO: Add more specific get next response tests as we have had issues
+
+func TestGetNextResponseOneFrameOnly(t *testing.T) {
+	// OMCI ME GetRequest for MsgTypes often needs only a single frame and
+	// it is a table of one octet values.  Make sure we decode it correctly
+
+	response1 := []uint8{
+		0, 250, 58, 10, 1, 31, 0, 0, 0, 64, 0,
+		4, 6, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 40,
+	}
+	// getNextSize is the size returned by the original Get request. Normally you would
+	// do many OMCI requests and append all the results (while decreasing size), but
+	// this is all in on packet.
+	//
+	// Do the buffer loop anyway
+	getNextSize := 23
+	remaining := getNextSize
+
+	dataBuffer := make([]byte, 0)
+	packets := []gopacket.Packet{
+		gopacket.NewPacket(response1, LayerTypeOMCI, gopacket.NoCopy),
+	}
+	for _, packet := range packets {
+		omciLayer := packet.Layer(LayerTypeOMCI)
+		assert.NotNil(t, omciLayer)
+
+		omciObj, omciOk := omciLayer.(*OMCI)
+		assert.True(t, omciOk)
+		assert.NotNil(t, omciObj)
+		assert.Equal(t, uint16(250), omciObj.TransactionID)
+		assert.Equal(t, GetNextResponseType, omciObj.MessageType)
+		assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+		assert.Equal(t, uint32(0), omciObj.MIC)
+		assert.Equal(t, uint16(40), omciObj.Length)
+
+		msgLayer := packet.Layer(LayerTypeGetNextResponse)
+		msgObj, msgOk := msgLayer.(*GetNextResponse)
+		assert.True(t, msgOk)
+		assert.NotNil(t, msgObj)
+		assert.Equal(t, me.Success, msgObj.Result)
+		assert.Equal(t, uint16(0x4000), msgObj.AttributeMask)
+		assert.Equal(t, 2, len(msgObj.Attributes))
+
+		for attrName, value := range msgObj.Attributes {
+			// Skip Entity ID attribute always stored in attribute list
+			if attrName == "ManagedEntityId" {
+				assert.Equal(t, uint16(0), value.(uint16))
+				continue
+			}
+			assert.Equal(t, "MessageTypeTable", attrName)
+			tmpBuffer, ok := value.([]byte)
+			assert.True(t, ok)
+
+			validOctets := len(tmpBuffer)
+			assert.NotZero(t, validOctets)
+			if validOctets > remaining {
+				validOctets = remaining
+			}
+			remaining -= validOctets
+			dataBuffer = append(dataBuffer, tmpBuffer[:validOctets]...)
+
+			assert.True(t, remaining >= 0)
+			if remaining == 0 {
+				break
+			}
+		}
+	}
+	bufSize := len(dataBuffer)
+	assert.Equal(t, getNextSize, bufSize)
+}
+
+func aTestFailingGetNextResponseTypeMeFrame(t *testing.T) {
+	//params := me.ParamData{
+	//	EntityID:   0,
+	//	Attributes: me.AttributeValueMap{
+	//		"Rmep5DatabaseTable": []uint8{
+	//			0,1,2,3,4,5,6,7,8,9,
+	//			10,11,12,13,14,15,16,17,18,19,
+	//			20,21,22,23,24,25,26,27,28,29,
+	//			30,
+	//		},
+	//	},
+	//}
+	//meInstance, err := me.NewDot1AgMepCcmDatabase(params)
+	//bitmask := uint16(2048)
+	//assert.NotNil(t, meInstance)
+	//assert.Nil(t, err)
+	//
+	//tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
+	//
+	//frame, omciErr := meframe.GenFrame(meInstance, GetNextResponseType, meframe.TransactionID(tid), meframe.Result(me.Success),
+	//	AttributeMask(bitmask))
+	//assert.NotNil(t, frame)
+	//assert.NotZero(t, len(frame))
+	//assert.Nil(t, omciErr)
+	//
+	/////////////////////////////////////////////////////////////////////
+	//// Now decode and compare
+	//cid := meInstance.GetClassID()
+	//assert.NotEqual(t, cid, 0)
+	//packet := gopacket.NewPacket(frame,  LayerTypeOMCI, gopacket.NoCopy)
+	//assert.NotNil(t, packet)
+	//
+	//omciLayer := packet.Layer( LayerTypeOMCI)
+	//assert.NotNil(t, omciLayer)
+	//
+	//omciObj, omciOk := omciLayer.(* OMCI)
+	//assert.NotNil(t, omciObj)
+	//assert.True(t, omciOk)
+	//assert.Equal(t, tid, omciObj.TransactionID)
+	//assert.Equal(t, GetNextResponseType, omciObj.MessageType)
+	//assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
+	//
+	//msgLayer := packet.Layer(LayerTypeGetNextResponse)
+	//assert.NotNil(t, msgLayer)
+	//
+	//msgObj, msgOk := msgLayer.(*GetNextResponse)
+	//assert.NotNil(t, msgObj)
+	//assert.True(t, msgOk)
+	//
+	//assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
+	//assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
+	//assert.Equal(t, meInstance.GetAttributeMask(), msgObj.AttributeMask)
+
+}
+
+func TestAllMessageTypes(t *testing.T) {
+	// Loop over all message types
+	for _, messageType := range allMessageTypes {
+		//typeTested := false
+		if testRoutine, ok := messageTypeTestFuncs[messageType]; ok {
+			// Loop over all Managed Entities that support that type
+			for _, managedEntity := range getMEsThatSupportAMessageType(messageType) {
+				// Call the test routine
+				testRoutine(t, managedEntity, BaselineIdent)
+				//typeTested = true
+			}
+		}
+		// Verify at least one test ran for this message type
+		// TODO: Enable once all tests are working -> assert.True(t, typeTested)
+	}
+	// Now for the extended message set message types we support
+	for _, messageType := range allExtendedMessageTypes {
+		trueMessageType := messageType - ExtendedTypeDecodeOffset
+
+		if testRoutine, ok := messageTypeTestFuncs[messageType]; ok {
+			// Loop over all Managed Entities that support that type
+			for _, managedEntity := range getMEsThatSupportAMessageType(trueMessageType) {
+				// Call the test routine
+				testRoutine(t, managedEntity, ExtendedIdent)
+				//typeTested = true
+			}
+		}
+		// Verify at least one test ran for this message type
+		// TODO: Enable once all tests are working -> assert.True(t, typeTested)
+	}
+}
+
+//func TestAllThatSupportAlarms(t *testing.T) {  TODO: Future
+//	// Loop over all Managed Entities and test those with Attributes that support
+//
+//	for _, managedEntity := range getMEsThatSupportAMessageType(messageType) {
+//		// Call the test routine
+//		testRoutine(t, managedEntity)
+//		//typeTested = true
+//	}
+//}
+
+func getAttributeNameSet(attributes me.AttributeValueMap) mapset.Set {
+	// TODO: For Classes with attribute masks that can set/get/... more than just
+	//       a single attribute, test a set/get of just a single attribute to verify
+	//       all encoding/decoding methods are working as expected.
+	names := mapset.NewSet()
+	for name := range attributes {
+		names.Add(name)
+	}
+	return names
+}
+
+func pickAValue(attrDef me.AttributeDefinition) interface{} {
+	constraint := attrDef.Constraint
+	defaultVal := attrDef.DefValue
+	size := attrDef.GetSize()
+	_, isOctetString := defaultVal.([]byte)
+
+	if attrDef.IsTableAttribute() || isOctetString {
+		// Table attributes treated as a string of octets.  If size is zero, it is
+		// most likely an attribute with variable size. Pick a random size that will
+		// fit into a simple frame (1-33 octets)
+		if size == 0 {
+			size = rand.Intn(32) + 1
+		}
+		value := make([]byte, size)
+		for octet := 0; octet < size; octet++ {
+			value[octet] = byte(octet & 0xff)
+		}
+		return value
+	}
+	switch size {
+	case 1:
+		// Try the default + 1 as a value. Since some defaults are zero
+		// and we want example frames without zeros in them.
+		if value, ok := defaultVal.(uint8); ok {
+			if constraint == nil {
+				return value + 1
+			}
+			if err := constraint(value + 1); err == nil {
+				return value + 1
+			}
+		}
+		return defaultVal.(uint8)
+
+	case 2:
+		// Try the default + 1 as a value. Since some defaults are zero
+		// and we want example frames without zeros in them.
+		if value, ok := defaultVal.(uint16); ok {
+			if constraint == nil {
+				return value + 1
+			}
+			if err := constraint(value + 1); err == nil {
+				return value + 1
+			}
+		}
+		return defaultVal.(uint16)
+
+	case 4:
+		// Try the default + 1 as a value. Since some defaults are zero
+		// and we want example frames without zeros in them.
+		if value, ok := defaultVal.(uint32); ok {
+			if constraint == nil {
+				return value + 1
+			}
+			if err := constraint(value + 1); err == nil {
+				return value + 1
+			}
+		}
+		return defaultVal.(uint32)
+
+	case 8:
+		// Try the default + 1 as a value. Since some defaults are zero
+		// and we want example frames without zeros in them.
+		if value, ok := defaultVal.(uint64); ok {
+			if constraint == nil {
+				return value + 1
+			}
+			if err := constraint(value + 1); err == nil {
+				return value + 1
+			}
+		}
+		return defaultVal.(uint64)
+
+	default:
+		size := attrDef.GetSize()
+		value := make([]uint8, size)
+		for index := 0; index < size; index++ {
+			value[index] = uint8(index & 0xFF)
+		}
+		return value
+	}
+}
diff --git a/meframe_test.go b/meframe_test.go
deleted file mode 100644
index 5a4d038..0000000
--- a/meframe_test.go
+++ /dev/null
@@ -1,2005 +0,0 @@
-/*
- * 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_test
-
-import (
-	mapset "github.com/deckarep/golang-set"
-	"github.com/google/gopacket"
-	. "github.com/opencord/omci-lib-go"
-	me "github.com/opencord/omci-lib-go/generated"
-	"github.com/stretchr/testify/assert"
-	"math/rand"
-	"testing"
-	"time"
-)
-
-var messageTypeTestFuncs map[MessageType]func(*testing.T, *me.ManagedEntity, DeviceIdent)
-
-func init() {
-	messageTypeTestFuncs = make(map[MessageType]func(*testing.T, *me.ManagedEntity, DeviceIdent), 0)
-
-	messageTypeTestFuncs[CreateRequestType] = testCreateRequestTypeMeFrame
-	messageTypeTestFuncs[CreateResponseType] = testCreateResponseTypeMeFrame
-	messageTypeTestFuncs[DeleteRequestType] = testDeleteRequestTypeMeFrame
-	messageTypeTestFuncs[DeleteResponseType] = testDeleteResponseTypeMeFrame
-	messageTypeTestFuncs[SetRequestType] = testSetRequestTypeMeFrame
-	messageTypeTestFuncs[SetResponseType] = testSetResponseTypeMeFrame
-	messageTypeTestFuncs[GetRequestType] = testGetRequestTypeMeFrame
-	messageTypeTestFuncs[GetResponseType] = testGetResponseTypeMeFrame
-	messageTypeTestFuncs[GetAllAlarmsRequestType] = testGetAllAlarmsRequestTypeMeFrame
-	messageTypeTestFuncs[GetAllAlarmsResponseType] = testGetAllAlarmsResponseTypeMeFrame
-	messageTypeTestFuncs[GetAllAlarmsNextRequestType] = testGetAllAlarmsNextRequestTypeMeFrame
-	messageTypeTestFuncs[GetAllAlarmsNextResponseType] = testGetAllAlarmsNextResponseTypeMeFrame
-	messageTypeTestFuncs[MibUploadRequestType] = testMibUploadRequestTypeMeFrame
-	messageTypeTestFuncs[MibUploadResponseType] = testMibUploadResponseTypeMeFrame
-	messageTypeTestFuncs[MibUploadNextRequestType] = testMibUploadNextRequestTypeMeFrame
-	messageTypeTestFuncs[MibUploadNextResponseType] = testMibUploadNextResponseTypeMeFrame
-	messageTypeTestFuncs[MibResetRequestType] = testMibResetRequestTypeMeFrame
-	messageTypeTestFuncs[MibResetResponseType] = testMibResetResponseTypeMeFrame
-	messageTypeTestFuncs[TestRequestType] = testTestRequestTypeMeFrame
-	messageTypeTestFuncs[TestResponseType] = testTestResponseTypeMeFrame
-
-	// For Download section, AR=0 if not response expected, AR=1 if response expected (last section of a window)4
-	messageTypeTestFuncs[StartSoftwareDownloadRequestType] = testStartSoftwareDownloadRequestTypeMeFrame
-	messageTypeTestFuncs[StartSoftwareDownloadResponseType] = testStartSoftwareDownloadResponseTypeMeFrame
-	messageTypeTestFuncs[DownloadSectionRequestType] = testDownloadSectionRequestTypeMeFrame
-	messageTypeTestFuncs[DownloadSectionResponseType] = testDownloadSectionResponseTypeMeFrame
-	messageTypeTestFuncs[EndSoftwareDownloadRequestType] = testEndSoftwareDownloadRequestTypeMeFrame
-	messageTypeTestFuncs[EndSoftwareDownloadResponseType] = testEndSoftwareDownloadResponseTypeMeFrame
-	messageTypeTestFuncs[ActivateSoftwareRequestType] = testActivateSoftwareRequestTypeMeFrame
-	messageTypeTestFuncs[ActivateSoftwareResponseType] = testActivateSoftwareResponseTypeMeFrame
-	messageTypeTestFuncs[CommitSoftwareRequestType] = testCommitSoftwareRequestTypeMeFrame
-	messageTypeTestFuncs[CommitSoftwareResponseType] = testCommitSoftwareResponseTypeMeFrame
-	messageTypeTestFuncs[SynchronizeTimeRequestType] = testSynchronizeTimeRequestTypeMeFrame
-	messageTypeTestFuncs[SynchronizeTimeResponseType] = testSynchronizeTimeResponseTypeMeFrame
-	messageTypeTestFuncs[RebootRequestType] = testRebootRequestTypeMeFrame
-	messageTypeTestFuncs[RebootResponseType] = testRebootResponseTypeMeFrame
-	messageTypeTestFuncs[GetNextRequestType] = testGetNextRequestTypeMeFrame
-	messageTypeTestFuncs[GetNextResponseType] = testGetNextResponseTypeMeFrame
-	messageTypeTestFuncs[GetCurrentDataRequestType] = testGetCurrentDataRequestTypeMeFrame
-	messageTypeTestFuncs[GetCurrentDataResponseType] = testGetCurrentDataResponseTypeMeFrame
-	messageTypeTestFuncs[SetTableRequestType] = testSetTableRequestTypeMeFrame
-	messageTypeTestFuncs[SetTableResponseType] = testSetTableResponseTypeMeFrame
-	messageTypeTestFuncs[AlarmNotificationType] = testAlarmNotificationTypeMeFrame
-	messageTypeTestFuncs[AttributeValueChangeType] = testAttributeValueChangeTypeMeFrame
-	messageTypeTestFuncs[TestResultType] = testTestResultTypeMeFrame
-
-	// Supported Extended message set types here
-	messageTypeTestFuncs[GetRequestType+ExtendedTypeDecodeOffset] = testGetRequestTypeMeFrame
-	messageTypeTestFuncs[GetResponseType+ExtendedTypeDecodeOffset] = testGetResponseTypeMeFrame
-
-	// For Download section, AR=0 if not response expected, AR=1 if response expected (last section of a window)
-	messageTypeTestFuncs[DownloadSectionRequestType+ExtendedTypeDecodeOffset] = testDownloadSectionRequestTypeMeFrame
-	// TODO: messageTypeTestFuncs[DownloadSectionRequestWithResponseType+ExtendedTypeDecodeOffset] = testDownloadSectionLastRequestTypeMeFrame
-	messageTypeTestFuncs[DownloadSectionResponseType+ExtendedTypeDecodeOffset] = testDownloadSectionResponseTypeMeFrame
-
-	messageTypeTestFuncs[AlarmNotificationType+ExtendedTypeDecodeOffset] = testAlarmNotificationTypeMeFrame
-	messageTypeTestFuncs[AttributeValueChangeType+ExtendedTypeDecodeOffset] = testAttributeValueChangeTypeMeFrame
-	messageTypeTestFuncs[TestResultType+ExtendedTypeDecodeOffset] = testTestResultTypeMeFrame
-}
-
-func getMEsThatSupportAMessageType(messageType MessageType) []*me.ManagedEntity {
-	msgType := me.MsgType(byte(messageType) & me.MsgTypeMask)
-
-	entities := make([]*me.ManagedEntity, 0)
-	for _, classID := range me.GetSupportedClassIDs() {
-		if managedEntity, err := me.LoadManagedEntityDefinition(classID); err.StatusCode() == me.Success {
-			supportedTypes := managedEntity.GetManagedEntityDefinition().GetMessageTypes()
-			if supportedTypes.Contains(msgType) {
-				entities = append(entities, managedEntity)
-			}
-		}
-	}
-	return entities
-}
-
-func TestFrameFormatNotYetSupported(t *testing.T) {
-	// We do not yet support a few message types for the extended frame formats.
-	// As we do, add appropriate tests and change this to one that is not supported
-	// Until all are supported
-
-	params := me.ParamData{
-		Attributes: me.AttributeValueMap{"MibDataSync": 0},
-	}
-	managedEntity, omciErr := me.NewOnuData(params)
-	assert.NotNil(t, omciErr)
-	assert.Equal(t, omciErr.StatusCode(), me.Success)
-
-	buffer, err := GenFrame(managedEntity, SetRequestType, FrameFormat(ExtendedIdent), TransactionID(1))
-	assert.Nil(t, buffer)
-	assert.NotNil(t, err)
-}
-
-// TODO: Add more specific get next response tests as we have had issues
-
-func TestGetNextResponseOneFrameOnly(t *testing.T) {
-	// OMCI ME GetRequest for MsgTypes often needs only a single frame and
-	// it is a table of one octet values.  Make sure we decode it correctly
-
-	response1 := []uint8{
-		0, 250, 58, 10, 1, 31, 0, 0, 0, 64, 0,
-		4, 6, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 0, 0,
-		0, 0, 0, 0, 0, 0, 0, 40,
-	}
-	// getNextSize is the size returned by the original Get request. Normally you would
-	// do many OMCI requests and append all the results (while decreasing size), but
-	// this is all in on packet.
-	//
-	// Do the buffer loop anyway
-	getNextSize := 23
-	remaining := getNextSize
-
-	dataBuffer := make([]byte, 0)
-	packets := []gopacket.Packet{
-		gopacket.NewPacket(response1, LayerTypeOMCI, gopacket.NoCopy),
-	}
-	for _, packet := range packets {
-		omciLayer := packet.Layer(LayerTypeOMCI)
-		assert.NotNil(t, omciLayer)
-
-		omciObj, omciOk := omciLayer.(*OMCI)
-		assert.True(t, omciOk)
-		assert.NotNil(t, omciObj)
-		assert.Equal(t, uint16(250), omciObj.TransactionID)
-		assert.Equal(t, GetNextResponseType, omciObj.MessageType)
-		assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
-		assert.Equal(t, uint32(0), omciObj.MIC)
-		assert.Equal(t, uint16(40), omciObj.Length)
-
-		msgLayer := packet.Layer(LayerTypeGetNextResponse)
-		msgObj, msgOk := msgLayer.(*GetNextResponse)
-		assert.True(t, msgOk)
-		assert.NotNil(t, msgObj)
-		assert.Equal(t, me.Success, msgObj.Result)
-		assert.Equal(t, uint16(0x4000), msgObj.AttributeMask)
-		assert.Equal(t, 2, len(msgObj.Attributes))
-
-		for attrName, value := range msgObj.Attributes {
-			// Skip Entity ID attribute always stored in attribute list
-			if attrName == "ManagedEntityId" {
-				assert.Equal(t, uint16(0), value.(uint16))
-				continue
-			}
-			assert.Equal(t, "MessageTypeTable", attrName)
-			tmpBuffer, ok := value.([]byte)
-			assert.True(t, ok)
-
-			validOctets := len(tmpBuffer)
-			assert.NotZero(t, validOctets)
-			if validOctets > remaining {
-				validOctets = remaining
-			}
-			remaining -= validOctets
-			dataBuffer = append(dataBuffer, tmpBuffer[:validOctets]...)
-
-			assert.True(t, remaining >= 0)
-			if remaining == 0 {
-				break
-			}
-		}
-	}
-	bufSize := len(dataBuffer)
-	assert.Equal(t, getNextSize, bufSize)
-}
-
-func aTestFailingGetNextResponseTypeMeFrame(t *testing.T) {
-	//params := me.ParamData{
-	//	EntityID:   0,
-	//	Attributes: me.AttributeValueMap{
-	//		"Rmep5DatabaseTable": []uint8{
-	//			0,1,2,3,4,5,6,7,8,9,
-	//			10,11,12,13,14,15,16,17,18,19,
-	//			20,21,22,23,24,25,26,27,28,29,
-	//			30,
-	//		},
-	//	},
-	//}
-	//meInstance, err := me.NewDot1AgMepCcmDatabase(params)
-	//bitmask := uint16(2048)
-	//assert.NotNil(t, meInstance)
-	//assert.Nil(t, err)
-	//
-	//tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-	//
-	//frame, omciErr := GenFrame(meInstance, GetNextResponseType, TransactionID(tid), Result(me.Success),
-	//	AttributeMask(bitmask))
-	//assert.NotNil(t, frame)
-	//assert.NotZero(t, len(frame))
-	//assert.Nil(t, omciErr)
-	//
-	/////////////////////////////////////////////////////////////////////
-	//// Now decode and compare
-	//cid := meInstance.GetClassID()
-	//assert.NotEqual(t, cid, 0)
-	//packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	//assert.NotNil(t, packet)
-	//
-	//omciLayer := packet.Layer(LayerTypeOMCI)
-	//assert.NotNil(t, omciLayer)
-	//
-	//omciObj, omciOk := omciLayer.(*OMCI)
-	//assert.NotNil(t, omciObj)
-	//assert.True(t, omciOk)
-	//assert.Equal(t, tid, omciObj.TransactionID)
-	//assert.Equal(t, GetNextResponseType, omciObj.MessageType)
-	//assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
-	//
-	//msgLayer := packet.Layer(LayerTypeGetNextResponse)
-	//assert.NotNil(t, msgLayer)
-	//
-	//msgObj, msgOk := msgLayer.(*GetNextResponse)
-	//assert.NotNil(t, msgObj)
-	//assert.True(t, msgOk)
-	//
-	//assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	//assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	//assert.Equal(t, meInstance.GetAttributeMask(), msgObj.AttributeMask)
-
-}
-
-func TestAllMessageTypes(t *testing.T) {
-	// Loop over all message types
-	for _, messageType := range allMessageTypes {
-		//typeTested := false
-		if testRoutine, ok := messageTypeTestFuncs[messageType]; ok {
-			// Loop over all Managed Entities that support that type
-			for _, managedEntity := range getMEsThatSupportAMessageType(messageType) {
-				// Call the test routine
-				testRoutine(t, managedEntity, BaselineIdent)
-				//typeTested = true
-			}
-		}
-		// Verify at least one test ran for this message type
-		// TODO: Enable once all tests are working -> assert.True(t, typeTested)
-	}
-	// Now for the extended message set message types we support
-	for _, messageType := range allExtendedMessageTypes {
-		trueMessageType := messageType - ExtendedTypeDecodeOffset
-
-		if testRoutine, ok := messageTypeTestFuncs[messageType]; ok {
-			// Loop over all Managed Entities that support that type
-			for _, managedEntity := range getMEsThatSupportAMessageType(trueMessageType) {
-				// Call the test routine
-				testRoutine(t, managedEntity, ExtendedIdent)
-				//typeTested = true
-			}
-		}
-		// Verify at least one test ran for this message type
-		// TODO: Enable once all tests are working -> assert.True(t, typeTested)
-	}
-}
-
-//func TestAllThatSupportAlarms(t *testing.T) {  TODO: Future
-//	// Loop over all Managed Entities and test those with Attributes that support
-//
-//	for _, managedEntity := range getMEsThatSupportAMessageType(messageType) {
-//		// Call the test routine
-//		testRoutine(t, managedEntity)
-//		//typeTested = true
-//	}
-//}
-
-func getAttributeNameSet(attributes me.AttributeValueMap) mapset.Set {
-	// TODO: For Classes with attribute masks that can set/get/... more than just
-	//       a single attribute, test a set/get of just a single attribute to verify
-	//       all encoding/decoding methods are working as expected.
-	names := mapset.NewSet()
-	for name, _ := range attributes {
-		names.Add(name)
-	}
-	return names
-}
-
-func pickAValue(attrDef me.AttributeDefinition) interface{} {
-	constraint := attrDef.Constraint
-	defaultVal := attrDef.DefValue
-	size := attrDef.GetSize()
-	_, isOctetString := defaultVal.([]byte)
-
-	if attrDef.IsTableAttribute() || isOctetString {
-		// Table attributes treated as a string of octets.  If size is zero, it is
-		// most likely an attribute with variable size. Pick a random size that will
-		// fit into a simple frame (1-33 octets)
-		if size == 0 {
-			size = rand.Intn(32) + 1
-		}
-		value := make([]byte, size)
-		for octet := 0; octet < size; octet++ {
-			value[octet] = byte(octet & 0xff)
-		}
-		return value
-	}
-	switch size {
-	case 1:
-		// Try the default + 1 as a value. Since some defaults are zero
-		// and we want example frames without zeros in them.
-		if value, ok := defaultVal.(uint8); ok {
-			if constraint == nil {
-				return value + 1
-			}
-			if err := constraint(value + 1); err == nil {
-				return value + 1
-			}
-		}
-		return defaultVal.(uint8)
-
-	case 2:
-		// Try the default + 1 as a value. Since some defaults are zero
-		// and we want example frames without zeros in them.
-		if value, ok := defaultVal.(uint16); ok {
-			if constraint == nil {
-				return value + 1
-			}
-			if err := constraint(value + 1); err == nil {
-				return value + 1
-			}
-		}
-		return defaultVal.(uint16)
-
-	case 4:
-		// Try the default + 1 as a value. Since some defaults are zero
-		// and we want example frames without zeros in them.
-		if value, ok := defaultVal.(uint32); ok {
-			if constraint == nil {
-				return value + 1
-			}
-			if err := constraint(value + 1); err == nil {
-				return value + 1
-			}
-		}
-		return defaultVal.(uint32)
-
-	case 8:
-		// Try the default + 1 as a value. Since some defaults are zero
-		// and we want example frames without zeros in them.
-		if value, ok := defaultVal.(uint64); ok {
-			if constraint == nil {
-				return value + 1
-			}
-			if err := constraint(value + 1); err == nil {
-				return value + 1
-			}
-		}
-		return defaultVal.(uint64)
-
-	default:
-		size := attrDef.GetSize()
-		value := make([]uint8, size)
-		for index := 0; index < size; index++ {
-			value[index] = uint8(index & 0xFF)
-		}
-		return value
-	}
-}
-
-func testCreateRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	// Generate the frame. Use a default Entity ID of zero, but for the
-	// OMCI library, we need to specify all supported Set-By-Create
-	params := me.ParamData{
-		EntityID:   uint16(0),
-		Attributes: make(me.AttributeValueMap, 0),
-	}
-	for _, attrDef := range managedEntity.GetAttributeDefinitions() {
-		if attrDef.Index == 0 {
-			continue // Skip entity ID, already specified
-
-		} else if attrDef.GetAccess().Contains(me.SetByCreate) {
-			params.Attributes[attrDef.GetName()] = pickAValue(attrDef)
-		}
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	frame, omciErr := GenFrame(meInstance, CreateRequestType, TransactionID(tid), FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, CreateRequestType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeCreateRequest)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*CreateRequest)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	assert.Equal(t, meInstance.GetAttributeValueMap(), msgObj.Attributes)
-}
-
-func testCreateResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	params := me.ParamData{
-		EntityID: uint16(0),
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-	result := me.Results(rand.Int31n(7))   // [0, 6] Not all types will be tested
-
-	// Always pass a failure mask, but should only get encoded if result == ParameterError
-	var mask uint16
-	for _, attrDef := range managedEntity.GetAttributeDefinitions() {
-		if attrDef.Index == 0 {
-			continue // Skip entity ID, already specified
-
-		} else if attrDef.GetAccess().Contains(me.SetByCreate) {
-			// Random 20% chance this parameter was bad
-			if rand.Int31n(5) == 0 {
-				mask |= attrDef.Mask
-			}
-		}
-	}
-	frame, omciErr := GenFrame(meInstance, CreateResponseType,
-		TransactionID(tid), Result(result), AttributeExecutionMask(mask), FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, CreateResponseType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeCreateResponse)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*CreateResponse)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	assert.Equal(t, result, msgObj.Result)
-
-	if result == me.ParameterError {
-		assert.Equal(t, mask, msgObj.AttributeExecutionMask)
-	} else {
-		assert.Zero(t, msgObj.AttributeExecutionMask)
-	}
-}
-
-func testDeleteRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	// Generate the frame. Use a default Entity ID of zero, but for the
-	// OMCI library, we need to specify all supported Set-By-Create
-	params := me.ParamData{
-		EntityID: uint16(0),
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-
-	frame, omciErr := GenFrame(meInstance, DeleteRequestType, TransactionID(tid), FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, DeleteRequestType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeDeleteRequest)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*DeleteRequest)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-}
-
-func testDeleteResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	params := me.ParamData{
-		EntityID: uint16(0),
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-	result := me.Results(rand.Int31n(7))   // [0, 6] Not all types will be tested
-
-	frame, omciErr := GenFrame(meInstance, DeleteResponseType, TransactionID(tid), Result(result),
-		FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, DeleteResponseType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeDeleteResponse)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*DeleteResponse)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	assert.Equal(t, result, msgObj.Result)
-}
-
-func testSetRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	params := me.ParamData{
-		EntityID:   uint16(0),
-		Attributes: make(me.AttributeValueMap, 0),
-	}
-	attrDefs := managedEntity.GetAttributeDefinitions()
-	tableAttrFound := false
-	for _, attrDef := range attrDefs {
-		if attrDef.Index == 0 {
-			continue // Skip entity ID, already specified
-		} else if attrDef.IsTableAttribute() {
-			tableAttrFound = true
-			continue // TODO: Skip table attributes for now
-		} else if attrDef.GetAccess().Contains(me.Write) {
-			params.Attributes[attrDef.GetName()] = pickAValue(attrDef)
-		}
-	}
-	if tableAttrFound && len(params.Attributes) == 0 {
-		// The only set attribute may have been a table and we do not have
-		// a test for that right now.
-		return
-	}
-	assert.NotEmpty(t, params.Attributes) // Need a parameter that is a table attribute
-	bitmask, attrErr := me.GetAttributesBitmap(attrDefs, getAttributeNameSet(params.Attributes))
-	assert.Nil(t, attrErr)
-
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-
-	frame, omciErr := GenFrame(meInstance, SetRequestType, TransactionID(tid),
-		AttributeMask(bitmask), FrameFormat(messageSet))
-	// some frames cannot fit all the attributes
-	if omciErr != nil {
-		if _, ok := omciErr.(*me.MessageTruncatedError); ok {
-			return
-		}
-	}
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, SetRequestType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeSetRequest)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*SetRequest)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	assert.Equal(t, meInstance.GetAttributeValueMap(), msgObj.Attributes)
-}
-
-func testSetResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	params := me.ParamData{
-		EntityID: uint16(0),
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-	result := me.Results(rand.Int31n(10))  // [0, 9] Not all types will be tested
-
-	// Always pass a failure mask, but should only get encoded if result == ParameterError
-	var unsupportedMask uint16
-	var failedMask uint16
-	attrDefs := managedEntity.GetAttributeDefinitions()
-	for _, attrDef := range attrDefs {
-		if attrDef.Index == 0 {
-			continue // Skip entity ID, already specified
-
-		} else if attrDef.GetAccess().Contains(me.Write) {
-			// Random 10% chance this parameter unsupported and
-			// 10% it failed
-			switch rand.Int31n(5) {
-			case 0:
-				unsupportedMask |= attrDef.Mask
-			case 1:
-				failedMask |= attrDef.Mask
-			}
-		}
-	}
-	bitmask, attrErr := me.GetAttributesBitmap(attrDefs, getAttributeNameSet(params.Attributes))
-	assert.Nil(t, attrErr)
-
-	frame, omciErr := GenFrame(meInstance, SetResponseType,
-		TransactionID(tid), Result(result),
-		AttributeMask(bitmask), FrameFormat(messageSet),
-		AttributeExecutionMask(failedMask),
-		UnsupportedAttributeMask(unsupportedMask))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, SetResponseType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeSetResponse)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*SetResponse)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	assert.Equal(t, result, msgObj.Result)
-
-	if result == me.AttributeFailure {
-		assert.Equal(t, failedMask, msgObj.FailedAttributeMask)
-		assert.Equal(t, unsupportedMask, msgObj.UnsupportedAttributeMask)
-	} else {
-		assert.Zero(t, msgObj.FailedAttributeMask)
-		assert.Zero(t, msgObj.UnsupportedAttributeMask)
-	}
-}
-
-func testGetRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	params := me.ParamData{
-		EntityID:   uint16(0),
-		Attributes: make(me.AttributeValueMap, 0),
-	}
-	attrDefs := managedEntity.GetAttributeDefinitions()
-	for _, attrDef := range attrDefs {
-		if attrDef.Index == 0 {
-			continue // Skip entity ID, already specified
-		} else if attrDef.GetAccess().Contains(me.Read) {
-			// Allow 'nil' as parameter value for GetRequests since we only need names
-			params.Attributes[attrDef.GetName()] = nil
-		}
-	}
-	assert.NotEmpty(t, params.Attributes) // Need a parameter that is a table attribute
-	bitmask, attrErr := me.GetAttributesBitmap(attrDefs, getAttributeNameSet(params.Attributes))
-	assert.Nil(t, attrErr)
-
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-
-	frame, omciErr := GenFrame(meInstance, GetRequestType, TransactionID(tid),
-		AttributeMask(bitmask), FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, GetRequestType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeGetRequest)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*GetRequest)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	assert.Equal(t, meInstance.GetAttributeMask(), msgObj.AttributeMask)
-}
-
-func testGetResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	params := me.ParamData{
-		EntityID:   uint16(0),
-		Attributes: make(me.AttributeValueMap),
-	}
-	// Add loop to test all valid result codes for this message type
-	validResultCodes := []me.Results{
-		me.Success,
-		me.ProcessingError,
-		me.NotSupported,
-		me.ParameterError,
-		me.UnknownEntity,
-		me.UnknownInstance,
-		me.DeviceBusy,
-		me.AttributeFailure,
-	}
-	for _, result := range validResultCodes {
-		tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-
-		// If success Results selected, set FailIfTruncated 50% of time to test
-		// overflow detection and failures periodically.  This is primarily for
-		// baseline message set for those MEs that may have lots of attribute space
-		// needed.  If extended message set, always fail if truncated since we should
-		// be able to stuff as much as we want (at least for now in these unit tests)
-		failIfTruncated := false
-		if result == me.Success && (rand.Int31n(2) == 1 || messageSet == ExtendedIdent) {
-			failIfTruncated = true
-		}
-		// Always pass a failure mask, but should only get encoded if result == ParameterError
-		var unsupportedMask uint16
-		var failedMask uint16
-		attrDefs := managedEntity.GetAttributeDefinitions()
-		for _, attrDef := range attrDefs {
-			if attrDef.Index == 0 {
-				continue // Skip entity ID, already specified
-
-			} else if attrDef.GetAccess().Contains(me.Read) {
-				// Random 5% chance this parameter unsupported and
-				// 5% it failed
-				switch rand.Int31n(20) {
-				default:
-					// TODO: Table attributes not yet supported.  For Table Attributes, figure out a
-					//       good way to unit test this and see if that can be extended to a more
-					//       general operation that provides the 'get-next' frames to the caller who
-					//		 wishes to serialize a table attribute.
-					if !attrDef.IsTableAttribute() {
-						params.Attributes[attrDef.GetName()] = pickAValue(attrDef)
-					}
-				case 0:
-					unsupportedMask |= attrDef.Mask
-				case 1:
-					failedMask |= attrDef.Mask
-				}
-			}
-		}
-		bitmask, attrErr := me.GetAttributesBitmap(attrDefs, getAttributeNameSet(params.Attributes))
-		assert.Nil(t, attrErr)
-
-		// Create the managed instance
-		meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-
-		frame, omciErr := GenFrame(meInstance, GetResponseType,
-			TransactionID(tid), Result(result),
-			AttributeMask(bitmask), FrameFormat(messageSet),
-			AttributeExecutionMask(failedMask),
-			UnsupportedAttributeMask(unsupportedMask),
-			FailIfTruncated(failIfTruncated))
-
-		// TODO: Need to test if err is MessageTruncatedError. Sometimes reported as
-		//       a proessing error
-		if omciErr != nil {
-			if _, ok := omciErr.(*me.MessageTruncatedError); ok {
-				return
-			}
-		}
-		assert.NotNil(t, frame)
-		assert.NotZero(t, len(frame))
-		assert.NotNil(t, err)
-		assert.Equal(t, err.StatusCode(), me.Success)
-
-		///////////////////////////////////////////////////////////////////
-		// Now decode and compare
-		packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-		assert.NotNil(t, packet)
-
-		omciLayer := packet.Layer(LayerTypeOMCI)
-		assert.NotNil(t, omciLayer)
-
-		omciObj, omciOk := omciLayer.(*OMCI)
-		assert.NotNil(t, omciObj)
-		assert.True(t, omciOk)
-		assert.Equal(t, tid, omciObj.TransactionID)
-		assert.Equal(t, GetResponseType, omciObj.MessageType)
-		assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-		msgLayer := packet.Layer(LayerTypeGetResponse)
-		// If requested Result was Success and FailIfTruncated is true, then we may
-		// fail (get nil layer) if too many attributes to fit in a frame
-		if result == me.Success && msgLayer == nil {
-			return // was expected
-		}
-		assert.NotNil(t, msgLayer)
-
-		msgObj, msgOk := msgLayer.(*GetResponse)
-		assert.NotNil(t, msgObj)
-		assert.True(t, msgOk)
-
-		assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-		assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-
-		switch msgObj.Result {
-		default:
-			assert.Equal(t, result, msgObj.Result)
-			assert.Zero(t, msgObj.FailedAttributeMask)
-			assert.Zero(t, msgObj.UnsupportedAttributeMask)
-
-		case me.Success:
-			assert.Equal(t, result, msgObj.Result)
-			assert.Zero(t, msgObj.FailedAttributeMask)
-			assert.Zero(t, msgObj.UnsupportedAttributeMask)
-			assert.Equal(t, meInstance.GetAttributeValueMap(), msgObj.Attributes)
-
-		case me.AttributeFailure:
-			// Should have been Success or AttributeFailure to start with
-			assert.True(t, result == me.Success || result == me.AttributeFailure)
-			if result == me.AttributeFailure {
-				assert.Equal(t, unsupportedMask, msgObj.UnsupportedAttributeMask)
-			}
-			// Returned may have more bits set in failed mask and less attributes
-			// since failIfTruncated is false and we may add more fail attributes
-			// since they do not fit. May also set only lower value (lower bits)
-			// if it turns out that the upper bits are already pre-assigned to the
-			// failure bits.
-			//
-			// Make sure any successful attributes were requested
-			meMap := meInstance.GetAttributeValueMap()
-			for name := range msgObj.Attributes {
-				getValue, ok := meMap[name]
-				assert.True(t, ok)
-				assert.NotNil(t, getValue)
-			}
-		}
-	}
-}
-
-func testGetAllAlarmsRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	params := me.ParamData{
-		EntityID: uint16(0),
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-	mode := uint8(rand.Int31n(2))          // [0, 1]
-
-	frame, omciErr := GenFrame(meInstance, GetAllAlarmsRequestType, TransactionID(tid),
-		RetrievalMode(mode), FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, GetAllAlarmsRequestType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeGetAllAlarmsRequest)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*GetAllAlarmsRequest)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	assert.Equal(t, mode, msgObj.AlarmRetrievalMode)
-}
-
-func testGetAllAlarmsResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	params := me.ParamData{
-		EntityID: uint16(0),
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	tid := uint16(rand.Int31n(0xFFFE) + 1)  // [1, 0xFFFF]
-	numOfCommands := uint16(rand.Int31n(5)) // [0, 5)
-
-	frame, omciErr := GenFrame(meInstance, GetAllAlarmsResponseType, TransactionID(tid),
-		SequenceNumberCountOrSize(numOfCommands), FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, GetAllAlarmsResponseType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeGetAllAlarmsResponse)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*GetAllAlarmsResponse)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	assert.Equal(t, numOfCommands, msgObj.NumberOfCommands)
-}
-
-func testGetAllAlarmsNextRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	params := me.ParamData{
-		EntityID: uint16(0),
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	tid := uint16(rand.Int31n(0xFFFE) + 1)   // [1, 0xFFFF]
-	sequenceNumber := uint16(rand.Int31n(5)) // [0, 5)
-
-	frame, omciErr := GenFrame(meInstance, GetAllAlarmsNextRequestType, TransactionID(tid),
-		SequenceNumberCountOrSize(sequenceNumber), FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, GetAllAlarmsNextRequestType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeGetAllAlarmsNextRequest)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*GetAllAlarmsNextRequest)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	assert.Equal(t, sequenceNumber, msgObj.CommandSequenceNumber)
-}
-
-func testGetAllAlarmsNextResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	params := me.ParamData{
-		EntityID: uint16(0),
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-
-	alarmInfo := AlarmOptions{
-		AlarmClassID:  123, // TODO: Real class here?
-		AlarmInstance: 456,
-		AlarmBitmap:   make([]byte, 28),
-	}
-	// TODO: Allow a 1 to 28 octet array to be used and zero fill any remainder...
-	for octet := 0; octet < 28; octet++ {
-		alarmInfo.AlarmBitmap[octet] = uint8(rand.Intn(256))
-	}
-	frame, omciErr := GenFrame(meInstance, GetAllAlarmsNextResponseType, TransactionID(tid),
-		Alarm(alarmInfo), FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, GetAllAlarmsNextResponseType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeGetAllAlarmsNextResponse)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*GetAllAlarmsNextResponse)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	assert.Equal(t, alarmInfo.AlarmClassID, msgObj.AlarmEntityClass)
-	assert.Equal(t, alarmInfo.AlarmInstance, msgObj.AlarmEntityInstance)
-	for octet := 0; octet < len(alarmInfo.AlarmBitmap); octet++ {
-		assert.Equal(t, alarmInfo.AlarmBitmap[octet], msgObj.AlarmBitMap[octet])
-	}
-}
-
-func testMibUploadRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	params := me.ParamData{
-		EntityID: uint16(0),
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-
-	frame, omciErr := GenFrame(meInstance, MibUploadRequestType, TransactionID(tid), FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, MibUploadRequestType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeMibUploadRequest)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*MibUploadRequest)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-}
-
-func testMibUploadResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	params := me.ParamData{
-		EntityID: uint16(0),
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	tid := uint16(rand.Int31n(0xFFFE) + 1)  // [1, 0xFFFF]
-	numOfCommands := uint16(rand.Int31n(5)) // [0, 5)
-
-	frame, omciErr := GenFrame(meInstance, MibUploadResponseType, TransactionID(tid),
-		SequenceNumberCountOrSize(numOfCommands), FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, MibUploadResponseType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeMibUploadResponse)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*MibUploadResponse)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	assert.Equal(t, numOfCommands, msgObj.NumberOfCommands)
-}
-
-func testMibUploadNextRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	params := me.ParamData{
-		EntityID: uint16(0),
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	seqNumber := uint16(rand.Int31n(0xFFFF)) // [0, 0xFFFE]
-	tid := uint16(rand.Int31n(0xFFFE) + 1)   // [1, 0xFFFF]
-
-	var frame []byte
-	frame, omciErr := GenFrame(meInstance, MibUploadNextRequestType, TransactionID(tid),
-		SequenceNumberCountOrSize(seqNumber), FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, MibUploadNextRequestType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeMibUploadNextRequest)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*MibUploadNextRequest)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, seqNumber, msgObj.CommandSequenceNumber)
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-}
-
-func testMibUploadNextResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	params := me.ParamData{
-		EntityID: uint16(0),
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-
-	// TODO: Since only baseline messages supported, send only one ME
-	uploadMe := meInstance
-
-	frame, omciErr := GenFrame(meInstance, MibUploadNextResponseType, TransactionID(tid),
-		Payload(uploadMe), FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, MibUploadNextResponseType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeMibUploadNextResponse)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*MibUploadNextResponse)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	assert.Equal(t, uploadMe.GetClassID(), msgObj.ReportedME.GetClassID())
-	assert.Equal(t, uploadMe.GetEntityID(), msgObj.ReportedME.GetEntityID())
-}
-
-func testMibResetRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	params := me.ParamData{
-		EntityID: uint16(0),
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-
-	frame, omciErr := GenFrame(meInstance, MibResetRequestType, TransactionID(tid), FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, MibResetRequestType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeMibResetRequest)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*MibResetRequest)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-}
-
-func testMibResetResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	params := me.ParamData{
-		EntityID: uint16(0),
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-	result := me.Results(rand.Int31n(7))   // [0, 6] Not all types will be tested
-
-	frame, omciErr := GenFrame(meInstance, MibResetResponseType, TransactionID(tid),
-		Result(result), FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, MibResetResponseType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeMibResetResponse)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*MibResetResponse)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	assert.Equal(t, result, msgObj.Result)
-}
-
-func testTestRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	// TODO: Implement
-}
-
-func testTestResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	// TODO: Implement
-}
-
-func testStartSoftwareDownloadRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	instance := uint16(0) // ONU-G
-	image := uint16(1)
-	params := me.ParamData{
-		EntityID: uint16((instance << 8) + image),
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-	options := SoftwareOptions{
-		WindowSize:   uint8(rand.Int31n(255)),                  // [0, 255]
-		ImageSize:    uint32(rand.Int31n(0x100000) + 0x100000), // [1 Meg, 2M-1]
-		CircuitPacks: []uint16{0},                              // [1 Meg, 2M-1]
-	}
-	frame, omciErr := GenFrame(meInstance, StartSoftwareDownloadRequestType,
-		TransactionID(tid), Software(options), FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, StartSoftwareDownloadRequestType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeStartSoftwareDownloadRequest)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*StartSoftwareDownloadRequest)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	assert.Equal(t, options.ImageSize, msgObj.ImageSize)
-	assert.Equal(t, len(options.CircuitPacks), int(msgObj.NumberOfCircuitPacks))
-
-	for index, circuitPack := range options.CircuitPacks {
-		assert.Equal(t, circuitPack, msgObj.CircuitPacks[index])
-	}
-}
-
-func testStartSoftwareDownloadResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	// TODO: Implement
-}
-
-func testDownloadSectionRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	// TODO: In future, also support slot/multiple download formats
-	instance := uint16(0)
-	image := uint16(rand.Intn(1)) // Image 0 or 1 for this test
-	params := me.ParamData{
-		EntityID: (instance << 8) + image,
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-	var data []byte
-
-	if messageSet == ExtendedIdent {
-		data = make([]byte, MaxDownloadSectionExtendedLength)
-	} else {
-		data = make([]byte, MaxDownloadSectionLength)
-	}
-	for index, _ := range data {
-		data[index] = byte(index & 0xFF)
-	}
-	options := SoftwareOptions{
-		SectionNumber: uint8(rand.Int31n(255)), // [0, 255]
-		Data:          data,
-	}
-	frame, omciErr := GenFrame(meInstance, DownloadSectionRequestType,
-		TransactionID(tid), Software(options), FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, DownloadSectionRequestType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeDownloadSectionRequest)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*DownloadSectionRequest)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	assert.Equal(t, options.SectionNumber, msgObj.SectionNumber)
-	assert.NotNil(t, msgObj.SectionData)
-	assert.Equal(t, options.Data, msgObj.SectionData)
-}
-
-func testDownloadSectionResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	instance := uint16(0)
-	image := uint16(rand.Intn(1)) // Image 0 or 1 for this test
-	params := me.ParamData{
-		EntityID: (instance << 8) + image,
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-	result := me.Results(rand.Int31n(7))   // [0, 6] Not all types will be tested
-	swOptions := SoftwareOptions{
-		SectionNumber: uint8(rand.Int31n(255)), // [0, 255]
-	}
-	var frame []byte
-	frame, omciErr := GenFrame(meInstance, DownloadSectionResponseType, TransactionID(tid),
-		Result(result), FrameFormat(messageSet), Software(swOptions))
-
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, DownloadSectionResponseType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeDownloadSectionResponse)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*DownloadSectionResponse)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	assert.Equal(t, result, msgObj.Result)
-	assert.Equal(t, swOptions.SectionNumber, msgObj.SectionNumber)
-}
-
-func testEndSoftwareDownloadRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	// TODO: Implement
-}
-
-func testEndSoftwareDownloadResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	// TODO: Implement
-}
-
-func testActivateSoftwareRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	// TODO: Implement
-}
-
-func testActivateSoftwareResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	// TODO: Implement
-}
-
-func testCommitSoftwareRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	// TODO: Implement
-}
-
-func testCommitSoftwareResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	// TODO: Implement
-}
-
-func testSynchronizeTimeRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	params := me.ParamData{
-		EntityID: uint16(0),
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-	tm := time.Now().UTC()
-	tmUnix := tm.Unix()
-
-	frame, omciErr := GenFrame(meInstance, SynchronizeTimeRequestType, TransactionID(tid),
-		Payload(tmUnix), FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, SynchronizeTimeRequestType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeSynchronizeTimeRequest)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*SynchronizeTimeRequest)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-
-	assert.Equal(t, uint16(tm.Year()), msgObj.Year)
-	assert.Equal(t, uint8(tm.Month()), msgObj.Month)
-	assert.Equal(t, uint8(tm.Day()), msgObj.Day)
-	assert.Equal(t, uint8(tm.Hour()), msgObj.Hour)
-	assert.Equal(t, uint8(tm.Minute()), msgObj.Minute)
-	assert.Equal(t, uint8(tm.Second()), msgObj.Second)
-}
-
-func testSynchronizeTimeResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	params := me.ParamData{
-		EntityID: uint16(0),
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-	result := me.Results(rand.Int31n(7))   // [0, 6] Not all types will be tested
-	successResult := uint8(rand.Int31n(2)) // [0, 1]
-
-	var frame []byte
-	frame, omciErr := GenFrame(meInstance, SynchronizeTimeResponseType, TransactionID(tid),
-		Result(result), SuccessResult(successResult), FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, SynchronizeTimeResponseType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeSynchronizeTimeResponse)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*SynchronizeTimeResponse)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	assert.Equal(t, result, msgObj.Result)
-	if result == me.Success {
-		assert.Equal(t, successResult, msgObj.SuccessResults)
-	} else {
-		assert.Zero(t, msgObj.SuccessResults)
-	}
-}
-
-func testRebootRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	params := me.ParamData{
-		EntityID: uint16(0),
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-	condition := uint8(rand.Int31n(3))     // [0, 3]
-
-	frame, omciErr := GenFrame(meInstance, RebootRequestType, TransactionID(tid),
-		RebootCondition(condition), FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, RebootRequestType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeRebootRequest)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*RebootRequest)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	assert.Equal(t, condition, msgObj.RebootCondition)
-}
-
-func testRebootResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	params := me.ParamData{
-		EntityID: uint16(0),
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-	result := me.Results(rand.Int31n(7))   // [0, 6] Not all types will be tested
-
-	frame, omciErr := GenFrame(meInstance, RebootResponseType, TransactionID(tid),
-		Result(result), FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, RebootResponseType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeRebootResponse)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*RebootResponse)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	assert.Equal(t, result, msgObj.Result)
-}
-
-func testGetNextRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	params := me.ParamData{
-		EntityID:   uint16(0),
-		Attributes: make(me.AttributeValueMap, 0),
-	}
-	// TODO: Loop over all table attributes for this class ID
-	// Find first attribute that is a table definition
-	// TODO: Test request of more than 1 attribute. G.988 specifies that a status
-	//       code of (3) should be returned.  Raise error during encode instead of
-	//       waiting for compliant ONU.  May want to have an 'ignore' to allow it.
-	attrDefs := managedEntity.GetAttributeDefinitions()
-	for _, attrDef := range attrDefs {
-		if attrDef.Index == 0 {
-			continue // Skip entity ID, already specified
-		} else if attrDef.IsTableAttribute() {
-			// TODO: Tables without a size are not supported. At least needs to be one octet
-			if attrDef.Size == 0 {
-				continue
-			}
-			// Allow 'nil' as parameter value for GetNextRequests since we only need names
-			params.Attributes[attrDef.GetName()] = nil
-			break
-		}
-	}
-	if len(params.Attributes) == 0 {
-		return
-	}
-	bitmask, attrErr := me.GetAttributesBitmap(attrDefs, getAttributeNameSet(params.Attributes))
-	assert.Nil(t, attrErr)
-
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	seqNumber := uint16(rand.Int31n(0xFFFF)) // [0, 0xFFFE]
-	tid := uint16(rand.Int31n(0xFFFE) + 1)   // [1, 0xFFFF]
-
-	frame, omciErr := GenFrame(meInstance, GetNextRequestType, TransactionID(tid),
-		SequenceNumberCountOrSize(seqNumber), AttributeMask(bitmask), FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, GetNextRequestType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeGetNextRequest)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*GetNextRequest)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	assert.Equal(t, meInstance.GetAttributeMask(), msgObj.AttributeMask)
-	assert.Equal(t, seqNumber, msgObj.SequenceNumber)
-}
-
-func testGetNextResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	params := me.ParamData{
-		EntityID:   uint16(0),
-		Attributes: make(me.AttributeValueMap, 0),
-	}
-	// TODO: Loop over result types (here and other responses with results)
-	result := me.Success // me.Results(rand.Int31n(7))  // [0, 6]
-	bitmask := uint16(0)
-	attrDefs := managedEntity.GetAttributeDefinitions()
-
-	// TODO: Loop over all table attributes for this class ID
-	if result == me.Success {
-		// Find first attribute that is a table definition
-		// TODO: Test request of more than 1 attribute. G.988 specifies that a status
-		//       code of (3) should be returned.  Raise error during encode instead of
-		//       waiting for compliant ONU.  May want to have an 'ignore' to allow it.
-		for _, attrDef := range attrDefs {
-			if attrDef.Index == 0 {
-				continue // Skip entity ID, already specified
-			} else if attrDef.IsTableAttribute() {
-				if len(params.Attributes) == 0 {
-					// Need a parameter that is a table attribute
-					return
-				}
-				params.Attributes[attrDef.GetName()] = pickAValue(attrDef)
-				break
-			}
-		}
-		if len(params.Attributes) == 0 {
-			return
-		}
-		assert.NotEmpty(t, params.Attributes) // Need a parameter that is a table attribute
-		var attrErr error
-		bitmask, attrErr = me.GetAttributesBitmap(attrDefs, getAttributeNameSet(params.Attributes))
-		assert.Nil(t, attrErr)
-	}
-	// Create the managed instance
-	meInstance, err := me.NewManagedEntity(managedEntity.GetManagedEntityDefinition(), params)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	tid := uint16(rand.Int31n(0xFFFE) + 1) // [1, 0xFFFF]
-
-	frame, omciErr := GenFrame(meInstance, GetNextResponseType, TransactionID(tid), Result(result),
-		AttributeMask(bitmask), FrameFormat(messageSet))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
-
-	///////////////////////////////////////////////////////////////////
-	// Now decode and compare
-	cid := meInstance.GetClassID()
-	assert.NotEqual(t, cid, 0)
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, GetNextResponseType, omciObj.MessageType)
-	assert.Equal(t, messageSet, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeGetNextResponse)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*GetNextResponse)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	assert.Equal(t, meInstance.GetAttributeMask(), msgObj.AttributeMask)
-
-	switch msgObj.Result {
-	default:
-		assert.Equal(t, result, msgObj.Result)
-
-	case me.Success:
-		assert.Equal(t, result, msgObj.Result)
-		// The attributes should be equal but for variable length table attribute (size = 0 in structure)
-		// we will have the frame padding returned as well.
-		for attrName, value := range meInstance.GetAttributeValueMap() {
-			attr, err := me.GetAttributeDefinitionByName(attrDefs, attrName)
-			assert.Nil(t, err)
-			assert.NotNil(t, attr)
-			assert.Equal(t, attrName, attr.GetName())
-			if attr.IsTableAttribute() {
-				instValue := value.([]byte)
-				msgValue := msgObj.Attributes[attrName].([]byte)
-				assert.True(t, len(instValue) <= len(msgValue))
-				assert.Equal(t, msgValue[:len(instValue)], instValue)
-			} else {
-				assert.Equal(t, value, msgObj.Attributes[attrName])
-			}
-		}
-	}
-}
-
-func testGetCurrentDataRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	// TODO: Implement
-}
-
-func testGetCurrentDataResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	// TODO: Implement
-}
-
-func testSetTableRequestTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	// TODO: Implement
-}
-
-func testSetTableResponseTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	// TODO: Implement
-}
-
-func testAlarmNotificationTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	// TODO: Implement
-}
-
-func testAttributeValueChangeTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	// TODO: Implement
-}
-
-func testTestResultTypeMeFrame(t *testing.T, managedEntity *me.ManagedEntity, messageSet DeviceIdent) {
-	// TODO: Implement
-}
diff --git a/messagetypes.go b/messagetypes.go
index 5e5dd74..be5c37b 100644
--- a/messagetypes.go
+++ b/messagetypes.go
@@ -18,14 +18,10 @@
 package omci
 
 import (
-	"encoding/binary"
-	"errors"
-	"fmt"
-	"github.com/google/gopacket"
 	me "github.com/opencord/omci-lib-go/generated"
 )
 
-// MessageType is the OMCI Message Type or'ed with the AR/AK flags as appropriate.
+// MessageType is the OMCI Message Type combined with the AR/AK flags as appropriate.
 type MessageType byte
 
 const (
@@ -72,11 +68,13 @@
 	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))
+
+	AlarmNotificationType    = MessageType(me.AlarmNotification)
+	AttributeValueChangeType = MessageType(me.AttributeValueChange)
+	TestResultType           = MessageType(me.TestResult)
 
 	// Support mapping of extended format types (use MSB reserved bit)
+
 	ExtendedTypeDecodeOffset = MessageType(byte(0x80))
 )
 
@@ -173,4160 +171,3 @@
 		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, 4)
-	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, 4+3)
-	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, 4)
-	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, 4+1)
-	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, 4+2)
-	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, 4+5)
-	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, 4+2)
-	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")
-	}
-	if omci.Extended {
-		if len(data) < 8 {
-			p.SetTruncated()
-			return errors.New("frame too small")
-		}
-		omci.AttributeMask = binary.BigEndian.Uint16(data[6:])
-	} else {
-		omci.AttributeMask = binary.BigEndian.Uint16(data[4:])
-	}
-	return nil
-}
-
-func decodeGetRequest(data []byte, p gopacket.PacketBuilder) error {
-	omci := &GetRequest{}
-	omci.MsgLayerType = LayerTypeGetRequest
-	return decodingLayerDecoder(omci, data, p)
-}
-
-func decodeGetRequestExtended(data []byte, p gopacket.PacketBuilder) error {
-	omci := &GetRequest{}
-	omci.MsgLayerType = LayerTypeGetRequest
-	omci.Extended = true
-	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")
-	}
-	maskOffset := 0
-	if omci.Extended {
-		maskOffset = 2
-	}
-	bytes, err := b.AppendBytes(2 + maskOffset)
-	if err != nil {
-		return err
-	}
-	if omci.Extended {
-		binary.BigEndian.PutUint16(bytes, uint16(2))
-	}
-	binary.BigEndian.PutUint16(bytes[maskOffset:], omci.AttributeMask)
-	return nil
-}
-
-func (omci *GetRequest) SerializeToExtended(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
-	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, 4+3)
-	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")
-	}
-	if omci.Extended {
-		if len(data) < 13 {
-			p.SetTruncated()
-			return errors.New("frame too small")
-		}
-		omci.Result = me.Results(data[6])
-		omci.AttributeMask = binary.BigEndian.Uint16(data[7:])
-
-		// If Attribute failed or Unknown, decode optional attribute mask
-		if omci.Result == me.AttributeFailure {
-			omci.UnsupportedAttributeMask = binary.BigEndian.Uint16(data[9:])
-			omci.FailedAttributeMask = binary.BigEndian.Uint16(data[11:])
-		}
-	} else {
-		omci.Result = me.Results(data[4])
-		omci.AttributeMask = binary.BigEndian.Uint16(data[5:])
-
-		// 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])
-		}
-	}
-	// 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.
-	firstOctet := 7
-	lastOctet := 36
-	if omci.Extended {
-		firstOctet = 13
-		lastOctet = len(data)
-	}
-
-	switch omci.Result {
-	case me.ProcessingError, me.NotSupported, me.UnknownEntity, me.UnknownInstance, me.DeviceBusy:
-		return nil // Done (do not try and decode attributes)
-
-	case me.AttributeFailure:
-		if !omci.Extended {
-			lastOctet = 32
-		}
-	}
-	omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask,
-		data[firstOctet:lastOctet], p, byte(GetResponseType))
-	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 decodeGetResponse(data []byte, p gopacket.PacketBuilder) error {
-	omci := &GetResponse{}
-	omci.MsgLayerType = LayerTypeGetResponse
-	return decodingLayerDecoder(omci, data, p)
-}
-
-func decodeGetResponseExtended(data []byte, p gopacket.PacketBuilder) error {
-	omci := &GetResponse{}
-	omci.MsgLayerType = LayerTypeGetResponse
-	omci.Extended = true
-	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")
-	}
-	resultOffset := 0
-	attributeErrExtra := 0
-
-	if omci.Extended {
-		resultOffset = 2
-		attributeErrExtra = 4 // Attribute mask + attribute error masks
-	}
-	// Space for result + mask (both types) + (len & error masks if extended)
-	buffer, err := b.AppendBytes(3 + resultOffset + attributeErrExtra)
-	if err != nil {
-		return err
-	}
-	// Save result and initial mask. Other header fields updated after
-	// attribute copy
-	buffer[resultOffset] = byte(omci.Result)
-	binary.BigEndian.PutUint16(buffer[resultOffset+1:], omci.AttributeMask)
-
-	// Validate all attributes support read
-	for attrName := range omci.Attributes {
-		var attr *me.AttributeDefinition
-		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:
-		if omci.Extended {
-			// Minimum length is 7 for extended an need to write error masks
-			binary.BigEndian.PutUint16(buffer, uint16(7))
-			binary.BigEndian.PutUint32(buffer[resultOffset+3:], 0)
-		}
-		break
-
-	case me.Success, me.AttributeFailure:
-		// TODO: Baseline only supported at this time)
-		var available int
-		if omci.Extended {
-			available = MaxExtendedLength - 18 - 4 // Less: header, mic
-		} else {
-			available = MaxBaselineLength - 11 - 4 - 8 // Less: header, failed attributes, length, mic
-		}
-		// Serialize to temporary buffer if we may need to reset values due to
-		// recoverable truncation errors
-		attributeBuffer := gopacket.NewSerializeBuffer()
-		var failedMask uint16
-		err, failedMask = meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask,
-			attributeBuffer, byte(GetResponseType), available, opts.FixLengths)
-
-		if err != nil {
-			return err
-		}
-		if failedMask != 0 {
-			// Not all attributes would fit
-			omci.FailedAttributeMask |= failedMask
-			omci.AttributeMask &= ^failedMask
-			omci.Result = me.AttributeFailure
-
-			// Adjust already recorded values
-			buffer[resultOffset] = byte(omci.Result)
-			binary.BigEndian.PutUint16(buffer[resultOffset+1:], omci.AttributeMask)
-		}
-		if omci.Extended {
-			// Set length and any failure masks
-			binary.BigEndian.PutUint16(buffer, uint16(len(attributeBuffer.Bytes())+7))
-
-			if omci.Result == me.AttributeFailure {
-				binary.BigEndian.PutUint16(buffer[resultOffset+3:], omci.UnsupportedAttributeMask)
-				binary.BigEndian.PutUint16(buffer[resultOffset+5:], omci.FailedAttributeMask)
-			} else {
-				binary.BigEndian.PutUint32(buffer[resultOffset+3:], 0)
-			}
-		}
-		// Copy over attributes to the original serialization buffer
-		var newSpace []byte
-
-		newSpace, err = b.AppendBytes(len(attributeBuffer.Bytes()))
-		if err != nil {
-			return err
-		}
-		copy(newSpace, attributeBuffer.Bytes())
-
-		if !omci.Extended {
-			// Calculate space left. Max  - msgType header - OMCI trailer - spacedUsedSoFar
-			bytesLeft := MaxBaselineLength - 4 - 8 - len(b.Bytes())
-
-			var remainingBytes []byte
-			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, 4+1)
-	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, 4+2)
-	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, 4+2)
-	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, 4+4+28)
-	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, 4)
-	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, 4+2)
-	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, 4+2)
-	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, 4+6)
-	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, 4)
-	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, 4+1)
-	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..6", 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 // Note: This zero padding is not present in the Extended Message Set
-	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)
-	}
-	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
-		me.ParamData{EntityID: omci.EntityInstance})
-	if omciErr.StatusCode() != me.Success {
-		return false, omciErr.GetError()
-	}
-	alarmMap := entity.GetAlarmMap()
-	if alarmMap == nil {
-		msg := "Managed Entity does not support Alarm notifications"
-		return false, errors.New(msg)
-	}
-	if _, ok := alarmMap[alarmNumber]; !ok {
-		msg := fmt.Sprintf("unsupported invalid alarm number: %v", 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)
-	}
-	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
-		me.ParamData{EntityID: omci.EntityInstance})
-	if omciErr.StatusCode() != me.Success {
-		return false, omciErr.GetError()
-	}
-	alarmMap := entity.GetAlarmMap()
-	if alarmMap == nil {
-		return false, errors.New("Managed Entity does not support Alarm notifications")
-	}
-	if _, ok := alarmMap[alarmNumber]; !ok {
-		msg := fmt.Sprintf("unsupported invalid alarm number: %v", 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)
-	}
-	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
-		me.ParamData{EntityID: omci.EntityInstance})
-	if omciErr.StatusCode() != me.Success {
-		return omciErr.GetError()
-	}
-	alarmMap := entity.GetAlarmMap()
-	if alarmMap == nil {
-		return errors.New("Managed Entity does not support Alarm notifications")
-	}
-	if _, ok := alarmMap[alarmNumber]; !ok {
-		msg := fmt.Sprintf("unsupported invalid alarm number: %v", 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)
-	}
-	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
-		me.ParamData{EntityID: omci.EntityInstance})
-	if omciErr.StatusCode() != me.Success {
-		return omciErr.GetError()
-	}
-	alarmMap := entity.GetAlarmMap()
-	if alarmMap == nil {
-		return errors.New("Managed Entity does not support Alarm notifications")
-	}
-	if _, ok := alarmMap[alarmNumber]; !ok {
-		msg := fmt.Sprintf("unsupported invalid alarm number: %v", 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, 4+28)
-	if err != nil {
-		return err
-	}
-	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
-		me.ParamData{EntityID: omci.EntityInstance})
-	if omciErr.StatusCode() != me.Success {
-		return omciErr.GetError()
-	}
-	// Is this an unsupported or vendor specific ME.  If so, it is not an error to decode
-	// the alarms.  We just cannot provide any alarm names.  Handle decode here.
-	classSupport := meDefinition.GetClassSupport()
-	isUnsupported := classSupport == me.UnsupportedManagedEntity ||
-		classSupport == me.UnsupportedVendorSpecificManagedEntity
-
-	mapOffset := 4
-	if omci.Extended {
-		mapOffset = 6
-		if len(data) < 6+28+1 {
-			p.SetTruncated()
-			return errors.New("frame too small")
-		}
-	}
-	// Look for a non-nil/not empty Alarm Map to determine if this ME supports alarms
-	if alarmMap := meDefinition.GetAlarmMap(); isUnsupported || (alarmMap != nil && len(alarmMap) > 0) {
-		for index, octet := range data[mapOffset : (AlarmBitmapSize/8)-mapOffset] {
-			omci.AlarmBitmap[index] = octet
-		}
-		if omci.Extended {
-			omci.AlarmSequenceNumber = data[mapOffset+(AlarmBitmapSize/8)]
-		} else {
-			padOffset := mapOffset + (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
-	}
-	return me.NewProcessingError("managed entity does not support alarm notifications")
-}
-
-func decodeAlarmNotification(data []byte, p gopacket.PacketBuilder) error {
-	omci := &AlarmNotificationMsg{}
-	omci.MsgLayerType = LayerTypeAlarmNotification
-	return decodingLayerDecoder(omci, data, p)
-}
-
-func decodeAlarmNotificationExtended(data []byte, p gopacket.PacketBuilder) error {
-	omci := &AlarmNotificationMsg{}
-	omci.MsgLayerType = LayerTypeAlarmNotification
-	omci.Extended = true
-	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
-	}
-	// TODO: Support of encoding AlarmNotification into supported types not yet supported
-	//meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
-	//	me.ParamData{EntityID: omci.EntityInstance})
-	//if omciErr.StatusCode() != me.Success {
-	//	return omciErr.GetError()
-	//}
-	//if !me.SupportsMsgType(meDefinition, me.AlarmNotification) {
-	//	return me.NewProcessingError("managed entity does not support Alarm Notification Message-Type")
-	//}
-	if omci.Extended {
-		bytes, err := b.AppendBytes(2 + (AlarmBitmapSize / 8) + 1)
-		if err != nil {
-			return err
-		}
-		binary.BigEndian.PutUint16(bytes, uint16((AlarmBitmapSize/8)+1))
-
-		for index, octet := range omci.AlarmBitmap {
-			bytes[2+index] = octet
-		}
-		bytes[2+(AlarmBitmapSize/8)] = omci.AlarmSequenceNumber
-	} else {
-		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, 4+2)
-	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: Support for encoding AVC into message type support not yet supported
-	//if !me.SupportsMsgType(meDefinition, me.AlarmNotification) {
-	//	return me.NewProcessingError("managed entity does not support Alarm Notification Message-Type")
-	//}
-	maskOffset := 4
-	if omci.Extended {
-		maskOffset = 6
-	}
-	omci.AttributeMask = binary.BigEndian.Uint16(data[maskOffset:])
-	// Attribute decode
-	omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask, data[maskOffset+2:],
-		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)
-}
-
-func decodeAttributeValueChangeExtended(data []byte, p gopacket.PacketBuilder) error {
-	omci := &AttributeValueChangeMsg{}
-	omci.MsgLayerType = LayerTypeAttributeValueChange
-	omci.Extended = true
-	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)
-	//	}
-	//}
-	var maskOffset int
-	var bytesAvailable int
-	if omci.Extended {
-		maskOffset = 2
-		bytesAvailable = MaxExtendedLength - 12 - 4
-	} else {
-		maskOffset = 0
-		bytesAvailable = MaxBaselineLength - 10 - 8
-	}
-	bytes, err := b.AppendBytes(maskOffset + 2)
-	if err != nil {
-		return err
-	}
-	binary.BigEndian.PutUint16(bytes[maskOffset:], omci.AttributeMask)
-
-	// Attribute serialization
-	attributeBuffer := gopacket.NewSerializeBuffer()
-	if err, _ = meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask,
-		attributeBuffer, byte(GetResponseType), bytesAvailable, false); err != nil {
-		return err
-	}
-
-	if omci.Extended {
-		binary.BigEndian.PutUint16(bytes, uint16(len(attributeBuffer.Bytes())+2))
-	}
-	bytes, err = b.AppendBytes(len(attributeBuffer.Bytes()))
-	if err != nil {
-		return err
-	}
-	copy(bytes, attributeBuffer.Bytes())
-	return err
-}
-
-func decodeTestRequest(data []byte, p gopacket.PacketBuilder) error {
-	// Peek at Managed Entity Type
-	if len(data) < 8 {
-		p.SetTruncated()
-		return errors.New("frame too small")
-	}
-	classID := binary.BigEndian.Uint16(data)
-
-	// Is it a Managed Entity class we support customized decode of?
-	switch me.ClassID(classID) {
-	default:
-		omci := &TestRequest{}
-		omci.MsgLayerType = LayerTypeTestRequest
-		return decodingLayerDecoder(omci, data, p)
-
-	case me.AniGClassID, me.ReAniGClassID, me.PhysicalPathTerminationPointReUniClassID,
-		me.ReUpstreamAmplifierClassID, me.ReDownstreamAmplifierClassID:
-		omci := &OpticalLineSupervisionTestRequest{}
-		omci.MsgLayerType = LayerTypeTestRequest
-		return decodingLayerDecoder(omci, data, p)
-	}
-}
-
-// TestRequest message
-type TestRequest struct {
-	MeBasePacket
-	Payload []byte
-}
-
-func (omci *TestRequest) String() string {
-	return fmt.Sprintf("%v, Request: %v octets", omci.MeBasePacket.String(), len(omci.Payload))
-}
-
-func (omci *TestRequest) TestRequest() []byte {
-	return omci.Payload
-}
-
-// 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, 4)
-	if err != nil {
-		return err
-	}
-
-	omci.Payload = make([]byte, MaxTestRequestLength)
-	copy(omci.Payload, omci.MeBasePacket.Payload)
-	return nil
-}
-
-// 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
-	}
-	if omci.Payload == nil {
-		return errors.New("Test Results payload is missing")
-	}
-
-	if len(omci.Payload) > MaxTestRequestLength {
-		msg := fmt.Sprintf("Invalid Test Request payload size. Received %v bytes, expected %v",
-			len(omci.Payload), MaxTestRequestLength)
-		return errors.New(msg)
-	}
-	bytes, err := b.AppendBytes(len(omci.Payload))
-	if err != nil {
-		return err
-	}
-
-	copy(bytes, omci.Payload)
-	return nil
-}
-
-type OpticalLineSupervisionTestRequest struct {
-	MeBasePacket
-	SelectTest               uint8  // Bitfield
-	GeneralPurposeBuffer     uint16 // Pointer to General Purpose Buffer ME
-	VendorSpecificParameters uint16 // Pointer to Octet String ME
-}
-
-func (omci *OpticalLineSupervisionTestRequest) String() string {
-	return fmt.Sprintf("Optical Line Supervision Test Result: SelectTest: %#x, Buffer: %#x, Params: %#x",
-		omci.SelectTest, omci.GeneralPurposeBuffer, omci.VendorSpecificParameters)
-}
-
-func (omci *OpticalLineSupervisionTestRequest) TestRequest() []byte {
-	return omci.Payload
-}
-
-// DecodeFromBytes decodes the given bytes of a Test Result Notification into this layer
-func (omci *OpticalLineSupervisionTestRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
-	// Common ClassID/EntityID decode in msgBase
-	err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+5)
-	if err != nil {
-		return err
-	}
-
-	omci.SelectTest = data[4]
-	omci.GeneralPurposeBuffer = binary.BigEndian.Uint16(data[5:])
-	omci.VendorSpecificParameters = binary.BigEndian.Uint16(data[7:])
-	return nil
-}
-
-// SerializeTo provides serialization of an Test Result notification message
-func (omci *OpticalLineSupervisionTestRequest) 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(8)
-	if err != nil {
-		return err
-	}
-
-	bytes[0] = omci.SelectTest
-	binary.BigEndian.PutUint16(bytes[1:], omci.GeneralPurposeBuffer)
-	binary.BigEndian.PutUint16(bytes[3:], omci.VendorSpecificParameters)
-	return nil
-}
-
-// TestResponse message
-type TestResponse struct {
-	MeBasePacket
-	Result me.Results
-}
-
-func (omci *TestResponse) String() string {
-	return fmt.Sprintf("%v, Results: %d (%v)", omci.MeBasePacket.String(), omci.Result, omci.Result)
-}
-
-// 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, 4+1)
-	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 Test requests
-	if !me.SupportsMsgType(meDefinition, me.Test) {
-		return me.NewProcessingError("managed entity does not support Test Message-Type")
-	}
-	omci.Result = me.Results(data[4])
-	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
-	}
-	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.Test) {
-		return me.NewProcessingError("managed entity does not support the Test Message-Type")
-	}
-	bytes, err := b.AppendBytes(1)
-	if err != nil {
-		return err
-	}
-	bytes[0] = byte(omci.Result)
-
-	if omci.Result > me.DeviceBusy {
-		msg := fmt.Sprintf("invalid results code: %v, must be 0..6", omci.Result)
-		return errors.New(msg)
-	}
-	return nil
-}
-
-/////////////////////////////////////////////////////////////////////////////
-//
-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, 4+4)
-	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, 4+3)
-	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
-}
-
-// DownloadSectionRequest data is bound by the message set in use. For the
-// Baseline message set use MaxDownloadSectionLength and for the Extended message
-// set, MaxDownloadSectionExtendedLength is provided
-type DownloadSectionRequest struct {
-	MeBasePacket  // Note: EntityInstance for software download is two specific values
-	SectionNumber byte
-	SectionData   []byte // 0 padding if final transfer requires only a partial block for baseline set
-}
-
-func (omci *DownloadSectionRequest) String() string {
-	return fmt.Sprintf("%v, Section #: %v, Data Length: %v",
-		omci.MeBasePacket.String(), omci.SectionNumber, len(omci.SectionData))
-}
-
-// 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, 4+1)
-	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")
-	}
-	if omci.Extended {
-		if len(data) < 7 {
-			p.SetTruncated()
-			return errors.New("frame too small")
-		}
-		if len(data[7:]) > MaxDownloadSectionExtendedLength {
-			return errors.New(fmt.Sprintf("software image data too large. Received %v, Max: %v",
-				len(data[7:]), MaxDownloadSectionExtendedLength))
-		}
-		omci.SectionData = make([]byte, len(data[7:]))
-		omci.SectionNumber = data[6]
-		copy(omci.SectionData, data[7:])
-	} else {
-		if len(data[5:]) != MaxDownloadSectionLength {
-			p.SetTruncated()
-			return errors.New(fmt.Sprintf("software image size invalid. Received %v, Expected: %v",
-				len(data[5:]), MaxDownloadSectionLength))
-		}
-		omci.SectionData = make([]byte, MaxDownloadSectionLength)
-		omci.SectionNumber = data[4]
-		copy(omci.SectionData, data[5:])
-	}
-	return nil
-}
-
-func decodeDownloadSectionRequest(data []byte, p gopacket.PacketBuilder) error {
-	omci := &DownloadSectionRequest{}
-	omci.MsgLayerType = LayerTypeDownloadSectionRequest
-	return decodingLayerDecoder(omci, data, p)
-}
-
-func decodeDownloadSectionRequestExtended(data []byte, p gopacket.PacketBuilder) error {
-	omci := &DownloadSectionRequest{}
-	omci.MsgLayerType = LayerTypeDownloadSectionRequest
-	omci.Extended = true
-	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")
-	}
-	sectionLength := len(omci.SectionData)
-	if omci.Extended {
-		if sectionLength > MaxDownloadSectionExtendedLength {
-			msg := fmt.Sprintf("invalid Download Section data length, must be <= %v, received: %v",
-				MaxDownloadSectionExtendedLength, sectionLength)
-			return me.NewProcessingError(msg)
-		}
-		// Append section data
-		bytes, err := b.AppendBytes(3 + sectionLength)
-		if err != nil {
-			return err
-		}
-		binary.BigEndian.PutUint16(bytes, uint16(1+sectionLength))
-		bytes[2] = omci.SectionNumber
-		copy(bytes[3:], omci.SectionData)
-	} else {
-		if sectionLength > MaxDownloadSectionLength {
-			msg := fmt.Sprintf("invalid Download Section data length, must be <= %v, received: %v",
-				MaxDownloadSectionLength, sectionLength)
-			return me.NewProcessingError(msg)
-		}
-		// Append section data
-		bytes, err := b.AppendBytes(1 + MaxDownloadSectionLength)
-		if err != nil {
-			return err
-		}
-		bytes[0] = omci.SectionNumber
-		copy(bytes[1:], omci.SectionData)
-
-		// Zero extended if needed
-		if sectionLength < MaxDownloadSectionLength {
-			copy(omci.SectionData[sectionLength:], lotsOfZeros[:MaxDownloadSectionLength-sectionLength])
-		}
-	}
-	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, 4+2)
-	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")
-	}
-	if omci.Extended {
-		if len(data) < 8 {
-			p.SetTruncated()
-			return errors.New("frame too small")
-		}
-		omci.Result = me.Results(data[6])
-		omci.SectionNumber = data[7]
-	} else {
-		omci.Result = me.Results(data[4])
-		omci.SectionNumber = data[5]
-	}
-	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)
-	}
-	return nil
-}
-
-func decodeDownloadSectionResponse(data []byte, p gopacket.PacketBuilder) error {
-	omci := &DownloadSectionResponse{}
-	omci.MsgLayerType = LayerTypeDownloadSectionResponse
-	return decodingLayerDecoder(omci, data, p)
-}
-
-func decodeDownloadSectionResponseExtended(data []byte, p gopacket.PacketBuilder) error {
-	omci := &DownloadSectionResponse{}
-	omci.MsgLayerType = LayerTypeDownloadSectionResponse
-	omci.Extended = true
-	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")
-	}
-	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)
-	}
-	if omci.Extended {
-		bytes, err := b.AppendBytes(4)
-		if err != nil {
-			return err
-		}
-		binary.BigEndian.PutUint16(bytes, uint16(2))
-		bytes[2] = byte(omci.Result)
-		bytes[3] = omci.SectionNumber
-	} else {
-		bytes, err := b.AppendBytes(2)
-		if err != nil {
-			return err
-		}
-		bytes[0] = byte(omci.Result)
-		bytes[1] = omci.SectionNumber
-	}
-	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, 4+7)
-	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[12]
-
-	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[13+(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[0:4], omci.CRC32)
-	binary.BigEndian.PutUint32(bytes[4:8], omci.ImageSize)
-	bytes[8] = omci.NumberOfInstances
-	for index := 0; index < int(omci.NumberOfInstances); index++ {
-		binary.BigEndian.PutUint16(bytes[9+(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, 4+2)
-	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(2 + (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, 4+1)
-	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, 4+1)
-	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, 4)
-	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
-	Result me.Results
-}
-
-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, 4+1)
-	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 Commit Software
-	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")
-	}
-	omci.Result = me.Results(data[4])
-	if omci.Result > me.Results(6) {
-		msg := fmt.Sprintf("invalid results for Commit Software response: %v, must be 0..6",
-			omci.Result)
-		return errors.New(msg)
-	}
-	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 Commit Software
-	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")
-	}
-	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 Commit Software response: %v, must be 0..6",
-			omci.Result)
-		return errors.New(msg)
-	}
-	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, 4+7)
-	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, 4+2)
-	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..6", 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, 4+1)
-	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, 4+1)
-	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, 4+4)
-	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, 4+3)
-	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
-}
-
-func decodeTestResult(data []byte, p gopacket.PacketBuilder) error {
-	// Peek at Managed Entity Type
-	if len(data) < 8 {
-		p.SetTruncated()
-		return errors.New("frame too small")
-	}
-	classID := binary.BigEndian.Uint16(data)
-
-	// Is it a Managed Entity class we support customized decode of?
-	switch me.ClassID(classID) {
-	default:
-		omci := &TestResultNotification{}
-		omci.MsgLayerType = LayerTypeTestResult
-		return decodingLayerDecoder(omci, data, p)
-
-	case me.AniGClassID, me.ReAniGClassID, me.PhysicalPathTerminationPointReUniClassID,
-		me.ReUpstreamAmplifierClassID, me.ReDownstreamAmplifierClassID:
-		omci := &OpticalLineSupervisionTestResult{}
-		omci.MsgLayerType = LayerTypeTestResult
-		return decodingLayerDecoder(omci, data, p)
-	}
-}
-
-func decodeTestResultExtended(data []byte, p gopacket.PacketBuilder) error {
-	// Peek at Managed Entity Type
-	if len(data) < 8 {
-		p.SetTruncated()
-		return errors.New("frame too small")
-	}
-	classID := binary.BigEndian.Uint16(data)
-
-	// Is it a Managed Entity class we support customized decode of?
-	switch me.ClassID(classID) {
-	default:
-		omci := &TestResultNotification{}
-		omci.MsgLayerType = LayerTypeTestResult
-		omci.Extended = true
-		return decodingLayerDecoder(omci, data, p)
-
-	case me.AniGClassID, me.ReAniGClassID, me.PhysicalPathTerminationPointReUniClassID,
-		me.ReUpstreamAmplifierClassID, me.ReDownstreamAmplifierClassID:
-		omci := &OpticalLineSupervisionTestResult{}
-		omci.MsgLayerType = LayerTypeTestResult
-		omci.Extended = true
-		return decodingLayerDecoder(omci, data, p)
-	}
-}
-
-type TestResultNotification struct {
-	MeBasePacket
-	Payload []byte
-}
-
-func (omci *TestResultNotification) TestResults() []byte {
-	return omci.Payload
-}
-
-func (omci *TestResultNotification) String() string {
-	return fmt.Sprintf("%v, Payload: %v octets", omci.MeBasePacket.String(), len(omci.Payload))
-}
-
-// DecodeFromBytes decodes the given bytes of a Test Result Notification into this layer
-func (omci *TestResultNotification) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
-	// Common ClassID/EntityID decode in msgBase
-	payloadOffset := 4
-	if omci.Extended {
-		payloadOffset = 6
-	}
-	err := omci.MeBasePacket.DecodeFromBytes(data, p, payloadOffset)
-	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 Test requests
-	if !me.SupportsMsgType(meDefinition, me.Test) {
-		return me.NewProcessingError("managed entity does not support Test Message-Type")
-	}
-	if omci.Extended {
-		if len(data) < 6 {
-			p.SetTruncated()
-			return errors.New("frame too small")
-		}
-		length := binary.BigEndian.Uint16(data[4:])
-		if len(data) < 6+int(length) {
-			p.SetTruncated()
-			return errors.New("frame too small")
-		}
-		omci.Payload = make([]byte, length)
-		copy(omci.Payload, data[6:])
-	} else {
-		omci.Payload = make([]byte, MaxTestResultsLength)
-		copy(omci.Payload, omci.MeBasePacket.Payload)
-	}
-	return nil
-}
-
-// SerializeTo provides serialization of an Test Result notification message
-func (omci *TestResultNotification) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
-	// Basic (common) OMCI Header is 8 octets
-	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 Test requests
-	if !me.SupportsMsgType(meDefinition, me.Test) {
-		return me.NewProcessingError("managed entity does not support Test Message-Type")
-	}
-	if omci.Payload == nil {
-		return errors.New("Test Results payload is missing")
-	}
-
-	payloadOffset := 0
-	maxSize := MaxTestResultsLength
-
-	if omci.Extended {
-		payloadOffset = 2
-		maxSize = MaxExtendedLength - 10 - 4
-	}
-	if len(omci.Payload) > maxSize {
-		msg := fmt.Sprintf("Invalid Test Results payload size. Received %v bytes, max expected %v",
-			len(omci.Payload), maxSize)
-		return errors.New(msg)
-	}
-	bytes, err := b.AppendBytes(len(omci.Payload) + payloadOffset)
-	if err != nil {
-		return err
-	}
-	if omci.Extended {
-		binary.BigEndian.PutUint16(bytes, uint16(len(omci.Payload)))
-	}
-	copy(bytes[payloadOffset:], omci.Payload)
-	return nil
-}
-
-// OpticalLineSupervisionTestResult provides a Optical Specific test results
-// message decode for the associated Managed Entities
-type OpticalLineSupervisionTestResult struct {
-	MeBasePacket
-	PowerFeedVoltageType     uint8  // Type = 1
-	PowerFeedVoltage         uint16 // value
-	ReceivedOpticalPowerType uint8  // Type = 3
-	ReceivedOpticalPower     uint16 // value
-	MeanOpticalLaunchType    uint8  // Type = 5
-	MeanOpticalLaunch        uint16 // value
-	LaserBiasCurrentType     uint8  // Type = 9
-	LaserBiasCurrent         uint16 // value
-	TemperatureType          uint8  // Type = 12
-	Temperature              uint16 // value
-
-	GeneralPurposeBuffer uint16 // Pointer to General Purpose Buffer ME
-}
-
-func (omci *OpticalLineSupervisionTestResult) String() string {
-	return fmt.Sprintf("Optical Line Supervision Test Result")
-}
-
-func (omci *OpticalLineSupervisionTestResult) TestResults() []byte {
-	return omci.MeBasePacket.Payload
-}
-
-// DecodeFromBytes decodes the given bytes of a Test Result Notification into this layer
-func (omci *OpticalLineSupervisionTestResult) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
-	// Common ClassID/EntityID decode in msgBase
-	payloadOffset := 4
-	if omci.Extended {
-		payloadOffset = 6
-	}
-	err := omci.MeBasePacket.DecodeFromBytes(data, p, payloadOffset+17)
-	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 Test requests
-	if !me.SupportsMsgType(meDefinition, me.Test) {
-		return me.NewProcessingError("managed entity does not support Test Message-Type")
-	}
-	// Note: Unsupported tests will have a type = 0 and the value should be zero
-	//       as well, but that constraint is not enforced at this time.
-	// Type = 1
-	omci.PowerFeedVoltageType = data[payloadOffset]
-	omci.PowerFeedVoltage = binary.BigEndian.Uint16(data[payloadOffset+1:])
-
-	// Type = 3
-	omci.ReceivedOpticalPowerType = data[payloadOffset+3]
-	omci.ReceivedOpticalPower = binary.BigEndian.Uint16(data[payloadOffset+4:])
-
-	// Type = 5
-	omci.MeanOpticalLaunchType = data[payloadOffset+6]
-	omci.MeanOpticalLaunch = binary.BigEndian.Uint16(data[payloadOffset+7:])
-
-	// Type = 9
-	omci.LaserBiasCurrentType = data[payloadOffset+9]
-	omci.LaserBiasCurrent = binary.BigEndian.Uint16(data[payloadOffset+10:])
-
-	// Type = 12
-	omci.TemperatureType = data[payloadOffset+12]
-	omci.Temperature = binary.BigEndian.Uint16(data[payloadOffset+13:])
-
-	omci.GeneralPurposeBuffer = binary.BigEndian.Uint16(data[payloadOffset+15:])
-	return nil
-}
-
-// SerializeTo provides serialization of an Test Result notification message
-func (omci *OpticalLineSupervisionTestResult) 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 Test requests
-	if !me.SupportsMsgType(meDefinition, me.Test) {
-		return me.NewProcessingError("managed entity does not support Test Message-Type")
-	}
-	payloadOffset := 0
-
-	if omci.Extended {
-		payloadOffset = 2
-	}
-	bytes, err := b.AppendBytes(payloadOffset + 17)
-	if err != nil {
-		return err
-	}
-
-	if omci.Extended {
-		binary.BigEndian.PutUint16(bytes, 17)
-	}
-	bytes[payloadOffset] = omci.PowerFeedVoltageType
-	binary.BigEndian.PutUint16(bytes[payloadOffset+1:], omci.PowerFeedVoltage)
-	bytes[payloadOffset+3] = omci.ReceivedOpticalPowerType
-	binary.BigEndian.PutUint16(bytes[payloadOffset+4:], omci.ReceivedOpticalPower)
-	bytes[payloadOffset+6] = omci.MeanOpticalLaunchType
-	binary.BigEndian.PutUint16(bytes[payloadOffset+7:], omci.MeanOpticalLaunch)
-	bytes[payloadOffset+9] = omci.LaserBiasCurrentType
-	binary.BigEndian.PutUint16(bytes[payloadOffset+10:], omci.LaserBiasCurrent)
-	bytes[payloadOffset+12] = omci.TemperatureType
-	binary.BigEndian.PutUint16(bytes[payloadOffset+13:], omci.Temperature)
-	binary.BigEndian.PutUint16(bytes[payloadOffset+15:], omci.GeneralPurposeBuffer)
-	return nil
-}
-
-/////////////////////////////////////////////////////////////////////////////
-//
-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
-	var offset int
-	if omci.Extended {
-		offset = 6
-	} else {
-		offset = 4
-	}
-	hdrSize := offset + 2
-	if len(data) < hdrSize {
-		p.SetTruncated()
-		return errors.New("frame too small")
-	}
-	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
-	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[offset:])
-	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
-	UnsupportedAttributeMask uint16
-	FailedAttributeMask      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
-	var offset, length int
-	if omci.Extended {
-		offset = 6
-		length = 7
-	} else {
-		offset = 4
-		length = 3
-	}
-	hdrSize := offset + length
-	if len(data) < hdrSize {
-		p.SetTruncated()
-		return errors.New("frame too small")
-	}
-	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
-	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.Result = me.Results(data[offset])
-	omci.AttributeMask = binary.BigEndian.Uint16(data[offset+1:])
-	switch omci.Result {
-	case me.ProcessingError, me.NotSupported, me.UnknownEntity, me.UnknownInstance, me.DeviceBusy:
-		return nil // Done (do not try and decode attributes)
-	case me.AttributeFailure:
-		if omci.Extended {
-			omci.UnsupportedAttributeMask = binary.BigEndian.Uint16(data[offset+3:])
-			omci.FailedAttributeMask = binary.BigEndian.Uint16(data[offset+5:])
-		} else {
-			omci.UnsupportedAttributeMask = binary.BigEndian.Uint16(data[32:])
-			omci.FailedAttributeMask = binary.BigEndian.Uint16(data[34:])
-		}
-	}
-	// 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 in a baseline GET
-	//                   Response. So this behaviour is anticipated here as well
-	//                   and will be allowed in favor of greater interoperability.
-	omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask, data[hdrSize:], p, byte(GetCurrentDataResponseType))
-	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
-	}
-	return errors.New("All Managed Entities have an EntityID attribute")
-}
-
-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")
-	}
-	var resultOffset, hdrSize int
-
-	if omci.Extended {
-		resultOffset = 2
-		hdrSize = resultOffset + 1 + 2 + 2 + 2 // length + result + masks
-	} else {
-		resultOffset = 0
-		hdrSize = resultOffset + 1 + 2 // length + result + attr-mask
-	}
-	bytes, err := b.AppendBytes(hdrSize)
-	if err != nil {
-		return err
-	}
-	bytes[resultOffset] = byte(omci.Result)
-	binary.BigEndian.PutUint16(bytes[resultOffset+1:], omci.AttributeMask)
-
-	// Validate all attributes support read
-	for attrName := range omci.Attributes {
-		var attr *me.AttributeDefinition
-		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:
-		if omci.Extended {
-			binary.BigEndian.PutUint16(bytes, 7) // Length
-			binary.BigEndian.PutUint32(bytes[resultOffset+3:], 0)
-		}
-		break
-
-	case me.Success, me.AttributeFailure:
-		var available int
-		if omci.Extended {
-			available = MaxExtendedLength - 10 - 3 - 4 - 4 // Less: header, result+mask, optional-masks mic
-		} else {
-			available = MaxBaselineLength - 8 - 3 - 4 - 8 // hdr, result+mask, optional-masks, trailer
-		}
-		// Serialize to temporary buffer if we may need to reset values due to
-		// recoverable truncation errors
-		attributeBuffer := gopacket.NewSerializeBuffer()
-		var failedMask uint16
-		err, failedMask = meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask,
-			attributeBuffer, byte(GetCurrentDataResponseType), available, opts.FixLengths)
-
-		if err != nil {
-			return err
-		}
-		if failedMask != 0 {
-			// Not all attributes would fit
-			omci.FailedAttributeMask |= failedMask
-			omci.AttributeMask &= ^failedMask
-			omci.Result = me.AttributeFailure
-
-			// Adjust already recorded values
-			bytes[resultOffset] = byte(omci.Result)
-			binary.BigEndian.PutUint16(bytes[resultOffset+1:], omci.AttributeMask)
-		}
-		if omci.Extended {
-			// Set length and any failure masks
-			binary.BigEndian.PutUint16(bytes, uint16(len(attributeBuffer.Bytes())+7))
-
-			if omci.Result == me.AttributeFailure {
-				binary.BigEndian.PutUint16(bytes[resultOffset+3:], omci.UnsupportedAttributeMask)
-				binary.BigEndian.PutUint16(bytes[resultOffset+5:], omci.FailedAttributeMask)
-			} else {
-				binary.BigEndian.PutUint32(bytes[resultOffset+3:], 0)
-			}
-		}
-		// Copy over attributes to the original serialization buffer
-		var newSpace []byte
-
-		newSpace, err = b.AppendBytes(len(attributeBuffer.Bytes()))
-		if err != nil {
-			return err
-		}
-		copy(newSpace, attributeBuffer.Bytes())
-
-		if !omci.Extended {
-			// Calculate space left. Max  - msgType header - OMCI trailer - spacedUsedSoFar
-			bytesLeft := MaxBaselineLength - 4 - 8 - len(b.Bytes())
-
-			var remainingBytes []byte
-			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
-}
-
-/////////////////////////////////////////////////////////////////////////////
-//
-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, 6+2)
-	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, 6+1)
-	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
-}
diff --git a/messagetypes_test.go b/messagetypes_test.go
index 69f8abe..a22e7ef 100644
--- a/messagetypes_test.go
+++ b/messagetypes_test.go
@@ -17,9 +17,6 @@
 package omci_test
 
 import (
-	"encoding/base64"
-	"encoding/binary"
-	"fmt"
 	"github.com/google/gopacket"
 	. "github.com/opencord/omci-lib-go"
 	me "github.com/opencord/omci-lib-go/generated"
@@ -100,11 +97,6 @@
 	TestResultType,
 }
 
-var allExtendedMessageTypes = [...]MessageType{
-	GetRequestType,
-	GetResponseType,
-}
-
 var allResults = [...]me.Results{
 	me.Success,
 	me.ProcessingError,
@@ -260,483 +252,8 @@
 	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
 }
 
-func TestCreateRequestDecode(t *testing.T) {
-	goodMessage := "000C440A010C01000400800003010000" +
-		"00000000000000000000000000000000" +
-		"000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0xc))
-	assert.Equal(t, omciMsg.MessageType, CreateRequestType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeCreateRequest)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*CreateRequest)
-	assert.True(t, ok2)
-	assert.Equal(t, request.EntityClass, me.GemPortNetworkCtpClassID)
-	assert.Equal(t, request.EntityInstance, uint16(0x100))
-
-	attributes := request.Attributes
-	assert.NotNil(t, attributes)
-
-	// As this is a create request, gather up all set-by-create attributes
-	// make sure we got them all, and nothing else
-	meDefinition, omciErr := me.LoadManagedEntityDefinition(request.EntityClass)
-	assert.NotNil(t, omciErr)
-	assert.Equal(t, omciErr.StatusCode(), me.Success)
-
-	attrDefs := meDefinition.GetAttributeDefinitions()
-
-	sbcMask := getSbcMask(meDefinition)
-	for index := uint(1); index < uint(len(attrDefs)); index++ {
-		attrName := attrDefs[index].GetName()
-
-		if sbcMask&uint16(1<<(uint)(16-index)) != 0 {
-			_, ok3 := attributes[attrName]
-			assert.True(t, ok3)
-		} else {
-			_, ok3 := attributes[attrName]
-			assert.False(t, ok3)
-		}
-		//fmt.Printf("Name: %v, Value: %v\n", attrName, attributes[attrName])
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err = gopacket.SerializeLayers(buffer, options, omciMsg, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestCreateRequestSerialize(t *testing.T) {
-	goodMessage := "000C440A010C0100040080000301000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x0c,
-		MessageType:   CreateRequestType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &CreateRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.GemPortNetworkCtpClassID,
-			EntityInstance: uint16(0x100),
-		},
-		Attributes: me.AttributeValueMap{
-			"PortId":                              0x400,
-			"TContPointer":                        0x8000,
-			"Direction":                           3,
-			"TrafficManagementPointerForUpstream": 0x100,
-			"TrafficDescriptorProfilePointerForUpstream":   0,
-			"PriorityQueuePointerForDownStream":            0,
-			"TrafficDescriptorProfilePointerForDownstream": 0,
-			"EncryptionKeyRing":                            0,
-		},
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestCreateResponseDecode(t *testing.T) {
-	goodMessage := "0157240a01100001000000000000000000000000000000000000000000000000000000000000000000000028a9ccbeb9"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0157))
-	assert.Equal(t, omciMsg.MessageType, CreateResponseType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeCreateResponse)
-	assert.NotNil(t, msgLayer)
-
-	response, ok2 := msgLayer.(*CreateResponse)
-	assert.True(t, ok2)
-	assert.NotNil(t, response)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestCreateResponseSerialize(t *testing.T) {
-	goodMessage := "0157240a01100001000000000000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x0157,
-		MessageType:   CreateResponseType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &CreateResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.GalEthernetProfileClassID,
-			EntityInstance: uint16(1),
-		},
-		Result:                 me.Success,
-		AttributeExecutionMask: uint16(0),
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestDeleteRequestDecode(t *testing.T) {
-	goodMessage := "0211460a00ab0202000000000000000000000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0211))
-	assert.Equal(t, omciMsg.MessageType, DeleteRequestType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeDeleteRequest)
-
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*DeleteRequest)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestDeleteRequestSerialize(t *testing.T) {
-	goodMessage := "0211460a00ab0202000000000000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x0211,
-		MessageType:   DeleteRequestType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &DeleteRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
-			EntityInstance: uint16(0x202),
-		},
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestDeleteResponseDecode(t *testing.T) {
-	goodMessage := "0211260a00ab0202000000000000000000000000000000000000000000000000000000000000000000000028013437fb"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0211))
-	assert.Equal(t, omciMsg.MessageType, DeleteResponseType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeDeleteResponse)
-
-	assert.NotNil(t, msgLayer)
-
-	response, ok2 := msgLayer.(*DeleteResponse)
-	assert.True(t, ok2)
-	assert.NotNil(t, response)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestDeleteResponseSerialize(t *testing.T) {
-	goodMessage := "0211260a00ab0202000000000000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x0211,
-		MessageType:   DeleteResponseType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &DeleteResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
-			EntityInstance: uint16(0x202),
-		},
-		Result: me.Success,
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestSetRequestDecode(t *testing.T) {
-	goodMessage := "0107480a01000000020000000000000000000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0107))
-	assert.Equal(t, omciMsg.MessageType, SetRequestType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeSetRequest)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*SetRequest)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestSetRequestSerialize(t *testing.T) {
-	goodMessage := "0107480a01000000020000000000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x0107,
-		MessageType:   SetRequestType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &SetRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.OnuGClassID,
-			EntityInstance: uint16(0),
-		},
-		AttributeMask: uint16(0x200),
-		Attributes:    me.AttributeValueMap{"AdministrativeState": byte(0)},
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestSetResponseDecode(t *testing.T) {
-	goodMessage := "0107280a01000000000000000000000000000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0107))
-	assert.Equal(t, omciMsg.MessageType, SetResponseType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeSetResponse)
-	assert.NotNil(t, msgLayer)
-
-	response, ok2 := msgLayer.(*SetResponse)
-	assert.True(t, ok2)
-	assert.NotNil(t, response)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestSetResponseSerialize(t *testing.T) {
-	goodMessage := "0107280a01000000000000000000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x0107,
-		MessageType:   SetResponseType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &SetResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.OnuGClassID,
-			EntityInstance: uint16(0),
-		},
-		Result: me.Success,
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-
-}
-
-func TestSetResponseTableFailedAttributesDecode(t *testing.T) {
-	// This is a SET Response with failed and unsupported attributes
-	// TODO:Implement
-}
-
-func TestSetResponseTableFailedAttributesSerialize(t *testing.T) {
-	// This is a SET Response with failed and unsupported attributes
-	// TODO:Implement
-}
-
-func TestGetRequestDecode(t *testing.T) {
-	goodMessage := "035e490a01070000004400000000000000000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x035e))
-	assert.Equal(t, omciMsg.MessageType, GetRequestType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeGetRequest)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*GetRequest)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestGetRequestSerialize(t *testing.T) {
-	goodMessage := "035e490a01070000004400000000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x035e,
-		MessageType:   GetRequestType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &GetRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.AniGClassID,
-			EntityInstance: uint16(0),
-		},
-		AttributeMask: uint16(0x0044),
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestGetResponseDecode(t *testing.T) {
-	goodMessage := "035e290a01070000000044dbcb05f10000000000000000000000000000000000000000000000000000000028"
+func TestGetSoftwareImageResponseDecode(t *testing.T) {
+	goodMessage := "035e290a00070000000400000102030405060708090a0b0c0d0e0f0000000000000000000000000000000028"
 	data, err := stringToPacket(goodMessage)
 	assert.NoError(t, err)
 
@@ -760,2233 +277,29 @@
 	assert.True(t, ok2)
 	assert.NotNil(t, response)
 	assert.Equal(t, response.Result, me.Success)
-	assert.Equal(t, response.AttributeMask, uint16(0x0044))
-	assert.Equal(t, response.Attributes["TransmitOpticalLevel"], uint16(0x05f1))
-	assert.Equal(t, response.Attributes["OpticalSignalLevel"], uint16(0xdbcb))
+	assert.Equal(t, response.AttributeMask, uint16(0x0400))
+	assert.Equal(t, response.Attributes["ImageHash"], toOctets("AAECAwQFBgcICQoLDA0ODw==")) // 0->f octets)
 
 	// Verify string output for message
 	packetString := packet.String()
 	assert.NotZero(t, len(packetString))
 }
 
-func TestGetResponseSerialize(t *testing.T) {
-	goodMessage := "035e290a01070000000044dbcb05f10000000000000000000000000000000000000000000000000000000028"
-
+func TestGetSoftwareImageResponseSerialize(t *testing.T) {
+	goodMessage := "035e290a00070000000400000102030405060708090a0b0c0d0e0f0000000000000000000000000000000028"
 	omciLayer := &OMCI{
 		TransactionID: 0x035e,
 		MessageType:   GetResponseType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
 	}
 	request := &GetResponse{
 		MeBasePacket: MeBasePacket{
-			EntityClass:    me.AniGClassID,
+			EntityClass:    me.SoftwareImageClassID,
 			EntityInstance: uint16(0),
 		},
 		Result:        0,
-		AttributeMask: uint16(0x0044),
-		Attributes: me.AttributeValueMap{
-			"TransmitOpticalLevel": uint16(0x05f1),
-			"OpticalSignalLevel":   uint16(0xdbcb)},
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-///////////////////////////////////////////////////////////////////////
-// Packet definitions for attributes of various types/sizes
-func toOctets(str string) []byte {
-	data, err := base64.StdEncoding.DecodeString(str)
-	if err != nil {
-		panic(fmt.Sprintf("Invalid Base-64 string: '%v'", str))
-	}
-	return data
-}
-
-func TestGetResponseSerializeTruncationFailure(t *testing.T) {
-	// Too much data and 'fix-length' is not specified.  This response has 26
-	// octets in the requested data, but only 25 octets available
-
-	omciLayer := &OMCI{
-		TransactionID: 0x035e,
-		MessageType:   GetResponseType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &GetResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.OnuGClassID,
-			EntityInstance: uint16(0),
-		},
-		Result:        0,
-		AttributeMask: uint16(0xE000),
-		Attributes: me.AttributeValueMap{
-			"VendorId":     toOctets("ICAgIA=="),
-			"Version":      toOctets("MAAAAAAAAAAAAAAAAAA="),
-			"SerialNumber": toOctets("AAAAAAAAAAA="),
-		},
-	}
-	// Test serialization and verify truncation failure
-	var options gopacket.SerializeOptions
-	options.FixLengths = false
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.Error(t, err)
-	assert.IsType(t, &me.MessageTruncatedError{}, err)
-}
-
-func TestGetResponseSerializeTruncationButOkay(t *testing.T) {
-	// Too much data and 'fix-length' is specified so it packs as much as
-	// possible and adjusts the failure masks
-
-	omciLayer := &OMCI{
-		TransactionID: 0x035e,
-		MessageType:   GetResponseType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	response := &GetResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.OnuGClassID,
-			EntityInstance: uint16(0),
-		},
-		Result:        0,
-		AttributeMask: uint16(0xE000),
-		Attributes: me.AttributeValueMap{
-			"VendorId":     toOctets("ICAgIA=="),
-			"Version":      toOctets("MAAAAAAAAAAAAAAAAAA="),
-			"SerialNumber": toOctets("AAAAAAAAAAA="),
-		},
-	}
-	// Test serialization and verify truncation failure
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, response)
-	assert.NoError(t, err)
-
-	// Now deserialize it and see if we have the proper result (Attribute Failure)
-	// and a non-zero failed mask
-	responsePacket := buffer.Bytes()
-	packet := gopacket.NewPacket(responsePacket, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer2 := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer2)
-
-	omciMsg2, ok := omciLayer2.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciLayer.TransactionID, omciMsg2.TransactionID)
-	assert.Equal(t, omciLayer.MessageType, GetResponseType)
-	assert.Equal(t, omciLayer.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciLayer.Length, uint16(40))
-
-	msgLayer2 := packet.Layer(LayerTypeGetResponse)
-	assert.NotNil(t, msgLayer2)
-
-	response2, ok2 := msgLayer2.(*GetResponse)
-	assert.True(t, ok2)
-	assert.Equal(t, me.AttributeFailure, response2.Result)
-	assert.NotZero(t, response2.AttributeMask)
-	assert.NotZero(t, response2.FailedAttributeMask)
-	assert.Zero(t, response2.UnsupportedAttributeMask)
-}
-
-func TestGetResponseTableFailedAttributesDecode(t *testing.T) {
-	// This is a GET Response with failed and unsupported attributes
-	// TODO:Implement
-}
-
-func TestGetResponseTableFailedAttributesSerialize(t *testing.T) {
-	// This is a GET Response with failed and unsupported attributes
-	// TODO:Implement
-}
-
-func TestGetResponseTableAttributeDecode(t *testing.T) {
-	// This is a GET Response for a table attribute. It should return the attribute
-	// size as a uint16.
-	// TODO:Implement
-}
-
-func TestGetResponseTableAttributeSerialize(t *testing.T) {
-	// This is a GET Response for a table attribute. It should return the attribute
-	// size as a uint16.
-	// TODO:Implement
-}
-
-func TestGetAllAlarmsRequestDecode(t *testing.T) {
-	goodMessage := "04454b0a00020000000000000000000000000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0445))
-	assert.Equal(t, omciMsg.MessageType, GetAllAlarmsRequestType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeGetAllAlarmsRequest)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*GetAllAlarmsRequest)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-	assert.Equal(t, request.AlarmRetrievalMode, byte(0))
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestGetAllAlarmsRequestSerialize(t *testing.T) {
-	goodMessage := "04454b0a00020000010000000000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x0445,
-		MessageType:   GetAllAlarmsRequestType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &GetAllAlarmsRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.OnuDataClassID,
-			EntityInstance: uint16(0),
-		},
-		AlarmRetrievalMode: byte(1),
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestGetAllAlarmsResponseDecode(t *testing.T) {
-	goodMessage := "04452b0a00020000000300000000000000000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0445))
-	assert.Equal(t, omciMsg.MessageType, GetAllAlarmsResponseType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeGetAllAlarmsResponse)
-	assert.NotNil(t, msgLayer)
-
-	response, ok2 := msgLayer.(*GetAllAlarmsResponse)
-	assert.True(t, ok2)
-	assert.NotNil(t, response)
-	assert.Equal(t, response.NumberOfCommands, uint16(3))
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestGetAllAlarmsResponseSerialize(t *testing.T) {
-	goodMessage := "04452b0a00020000000300000000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x0445,
-		MessageType:   GetAllAlarmsResponseType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &GetAllAlarmsResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.OnuDataClassID,
-			EntityInstance: uint16(0),
-		},
-		NumberOfCommands: uint16(3),
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestGetAllAlarmsNextRequestDecode(t *testing.T) {
-	goodMessage := "02344c0a00020000000000000000000000000000000000000000000000000000000000000000000000000028"
-
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0234))
-	assert.Equal(t, omciMsg.MessageType, GetAllAlarmsNextRequestType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeGetAllAlarmsNextRequest)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*GetAllAlarmsNextRequest)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestGetAllAlarmsNextRequestSerialize(t *testing.T) {
-	goodMessage := "02344c0a00020000000000000000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x0234,
-		MessageType:   GetAllAlarmsNextRequestType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &GetAllAlarmsNextRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.OnuDataClassID,
-			EntityInstance: uint16(0),
-		},
-		CommandSequenceNumber: uint16(0),
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestGetAllAlarmsNextResponseDecode(t *testing.T) {
-	goodMessage := "02342c0a00020000000b01028000000000000000000000000000000000000000000000000000000000000028f040fc87"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0234))
-	assert.Equal(t, omciMsg.MessageType, GetAllAlarmsNextResponseType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeGetAllAlarmsNextResponse)
-	assert.NotNil(t, msgLayer)
-
-	response, ok2 := msgLayer.(*GetAllAlarmsNextResponse)
-	assert.True(t, ok2)
-	assert.NotNil(t, response)
-
-	var alarms [224 / 8]byte
-	alarms[0] = 0x80
-	assert.Equal(t, response.AlarmEntityClass, me.PhysicalPathTerminationPointEthernetUniClassID)
-	assert.Equal(t, response.AlarmEntityInstance, uint16(0x102))
-	assert.Equal(t, response.AlarmBitMap, alarms)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestGetAllAlarmsNextResponseSerialize(t *testing.T) {
-	goodMessage := "02342c0a00020000000b01028000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x0234,
-		MessageType:   GetAllAlarmsNextResponseType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	var alarms [224 / 8]byte
-	alarms[0] = 0x80
-
-	request := &GetAllAlarmsNextResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.OnuDataClassID,
-			EntityInstance: uint16(0),
-		},
-		AlarmEntityClass:    me.PhysicalPathTerminationPointEthernetUniClassID,
-		AlarmEntityInstance: uint16(0x102),
-		AlarmBitMap:         alarms,
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestGetAllAlarmsNextResponseBadCommandNumberDecode(t *testing.T) {
-	// Test of a GetNext Response that results when an invalid command number
-	// is requested. In the case where the ONU receives a get all alarms next
-	// request message in which the command sequence number is out of range,
-	// the ONU should respond with a message in which bytes 9 to 40 are all
-	// set to 0. This corresponds to a response with entity class 0, entity
-	// instance 0, and bit map all 0s.
-	//TODO: Implement
-}
-
-func TestGetAllAlarmsNextResponseBadCommandNumberSerialize(t *testing.T) {
-	// Test of a GetNext Response that results when an invalid command number
-	// is requested.
-	//TODO: Implement
-}
-
-func TestMibUploadRequestDecode(t *testing.T) {
-	goodMessage := "03604d0a00020000000000000000000000000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0360))
-	assert.Equal(t, omciMsg.MessageType, MibUploadRequestType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-	msgLayer := packet.Layer(LayerTypeMibUploadRequest)
-
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*MibUploadRequest)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestMibUploadRequestSerialize(t *testing.T) {
-	goodMessage := "03604d0a00020000000000000000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x0360,
-		MessageType:   MibUploadRequestType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	var alarms [224 / 8]byte
-	alarms[0] = 0x80
-
-	request := &MibUploadRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.OnuDataClassID,
-			EntityInstance: uint16(0),
-		},
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestMibUploadResponse(t *testing.T) {
-	goodMessage := "03602d0a00020000011200000000000000000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0360))
-	assert.Equal(t, omciMsg.MessageType, MibUploadResponseType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeMibUploadResponse)
-	assert.NotNil(t, msgLayer)
-
-	response, ok2 := msgLayer.(*MibUploadResponse)
-	assert.True(t, ok2)
-	assert.NotNil(t, response)
-	assert.Equal(t, response.NumberOfCommands, uint16(0x112))
-}
-
-func TestMibUploadResponseSerialize(t *testing.T) {
-	goodMessage := "03602d0a00020000011200000000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x0360,
-		MessageType:   MibUploadResponseType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	var alarms [224 / 8]byte
-	alarms[0] = 0x80
-
-	request := &MibUploadResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.OnuDataClassID,
-			EntityInstance: uint16(0),
-		},
-		NumberOfCommands: uint16(0x112),
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestMibUploadNextRequestDecode(t *testing.T) {
-	goodMessage := "02864e0a00020000003a00000000000000000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0286))
-	assert.Equal(t, omciMsg.MessageType, MibUploadNextRequestType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeMibUploadNextRequest)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*MibUploadNextRequest)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-	assert.Equal(t, request.CommandSequenceNumber, uint16(0x3a))
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestMibUploadNextRequestSerialize(t *testing.T) {
-	goodMessage := "02864e0a00020000003a00000000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x0286,
-		MessageType:   MibUploadNextRequestType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &MibUploadNextRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.OnuDataClassID,
-			EntityInstance: uint16(0),
-		},
-		CommandSequenceNumber: uint16(0x3a),
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestMibUploadNextResponseDecode(t *testing.T) {
-	goodMessage := "02862e0a0002000001150000fff0000000000000000000010100000000010000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0286))
-	assert.Equal(t, omciMsg.MessageType, MibUploadNextResponseType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeMibUploadNextResponse)
-	assert.NotNil(t, msgLayer)
-
-	response, ok2 := msgLayer.(*MibUploadNextResponse)
-	assert.True(t, ok2)
-	assert.NotNil(t, response)
-	assert.Equal(t, response.ReportedME.GetClassID(), me.PriorityQueueClassID)
-	assert.Equal(t, response.ReportedME.GetEntityID(), uint16(0))
-
-	attributes := me.AttributeValueMap{
-		"QueueConfigurationOption":                            byte(0),
-		"MaximumQueueSize":                                    uint16(0),
-		"AllocatedQueueSize":                                  uint16(0),
-		"DiscardBlockCounterResetInterval":                    uint16(0),
-		"ThresholdValueForDiscardedBlocksDueToBufferOverflow": uint16(0),
-		"RelatedPort":                                         uint32(16842752),
-		"TrafficSchedulerPointer":                             uint16(0),
-		"Weight":                                              byte(1),
-		"BackPressureOperation":                               uint16(0),
-		"BackPressureTime":                                    uint32(0),
-		"BackPressureOccurQueueThreshold":                     uint16(0),
-		"BackPressureClearQueueThreshold":                     uint16(0),
-	}
-	for name, value := range attributes {
-		pktValue, err := response.ReportedME.GetAttribute(name)
-		assert.Nil(t, err)
-		assert.Equal(t, pktValue, value)
-	}
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestMibUploadNextResponseSerialize(t *testing.T) {
-	goodMessage := "02862e0a0002000001150000fff0000000000000000000010100000000010000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x0286,
-		MessageType:   MibUploadNextResponseType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	paramData := me.ParamData{
-		EntityID: uint16(0),
-		Attributes: me.AttributeValueMap{
-			"QueueConfigurationOption":                            byte(0),
-			"MaximumQueueSize":                                    uint16(0),
-			"AllocatedQueueSize":                                  uint16(0),
-			"DiscardBlockCounterResetInterval":                    uint16(0),
-			"ThresholdValueForDiscardedBlocksDueToBufferOverflow": uint16(0),
-			"RelatedPort":                                         uint32(16842752),
-			"TrafficSchedulerPointer":                             uint16(0),
-			"Weight":                                              byte(1),
-			"BackPressureOperation":                               uint16(0),
-			"BackPressureTime":                                    uint32(0),
-			"BackPressureOccurQueueThreshold":                     uint16(0),
-			"BackPressureClearQueueThreshold":                     uint16(0),
-		},
-	}
-	reportedME, err := me.NewPriorityQueue(paramData)
-	assert.NotNil(t, err)
-	assert.Equal(t, err.StatusCode(), me.Success)
-
-	request := &MibUploadNextResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.OnuDataClassID,
-			EntityInstance: uint16(0),
-		},
-		ReportedME: *reportedME,
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	omciErr := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, omciErr)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestMibUploadNextResponseBadCommandNumberDecode(t *testing.T) {
-	// Test of a MIB Upload next Response that results when an invalid command number.
-	// Note that if all attributes of a managed entity do not fit within one MIB
-	// upload next response message, the attributes will be split over several
-	// messages. The OLT can use the information in the attribute mask to determine
-	// which attribute values are reported in which MIB upload next response message.
-	//TODO: Implement
-}
-
-func TestMibUploadNextResponseBadCommandNumberSerialize(t *testing.T) {
-	// Test of a MIB Upload next Response that results when an invalid command number
-	// is requested.
-	//TODO: Implement
-}
-
-// TODO: Create request/response tests for all of the following types
-//Test,
-//                    1                   2                   3                   4
-//  1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4
-// 0004530a00070001ff000f424001000100000000000000000000000000000000000000000000000000000028
-// 0004530a
-//         00070001             - ONU-G instance 0001
-//                 ff           - window size - 1
-//                   000f4240   - image size
-//                           01
-//                             000100000000000000000000000000000000000000000000000000000028
-func TestStartSoftwareDownloadRequestDecode(t *testing.T) {
-	goodMessage := "0004530a00070001ff000f424001000100000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, uint16(0x0004), omciMsg.TransactionID)
-	assert.Equal(t, StartSoftwareDownloadRequestType, omciMsg.MessageType)
-	assert.True(t, omciMsg.ResponseExpected)
-	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
-	assert.Equal(t, uint16(40), omciMsg.Length)
-
-	msgLayer := packet.Layer(LayerTypeStartSoftwareDownloadRequest)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*StartSoftwareDownloadRequest)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-	assert.Equal(t, uint8(0xff), request.WindowSize)
-	assert.Equal(t, uint32(0x000f4240), request.ImageSize)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestStartSoftwareDownloadRequestSerialize(t *testing.T) {
-	//// TODO: Need to complete implementation & debug this
-	//goodMessage := "0000530a0007000113000f424001000100000000000000000000000000000000000000000000000000000028"
-	//
-	//omciLayer := &OMCI{
-	//	TransactionID: 0x01,
-	//	MessageType:   StartSoftwareDownloadRequestType,
-	//	// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-	//	// Length:           0x28,						// Optional, defaults to 40 octets
-	//}
-	//request := &StartSoftwareDownloadRequest{
-	//	MeBasePacket: MeBasePacket{
-	//		EntityClass: OnuDataClassID,
-	//		// Default Instance ID is 0
-	//	},
-	//}
-	//// Test serialization back to former string
-	//var options gopacket.SerializeOptions
-	//options.FixLengths = true
-	//
-	//buffer := gopacket.NewSerializeBuffer()
-	//err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	//assert.NoError(t, err)
-	//
-	//outgoingPacket := buffer.Bytes()
-	//reconstituted := packetToString(outgoingPacket)
-	//assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestStartSoftwareDownloadResponseDecode(t *testing.T) {
-	// TODO: Need to complete implementation & debug this
-	//goodMessage := ""
-	//data, err := stringToPacket(goodMessage)
-	//assert.NoError(t, err)
-	//
-	//packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	//assert.NotNil(t, packet)
-	//
-	//omciLayer := packet.Layer(LayerTypeOMCI)
-	//assert.NotNil(t, omciLayer)
-	//
-	//omciMsg, ok := omciLayer.(*OMCI)
-	//assert.True(t, ok)
-	//assert.Equal(t, omciMsg.TransactionID, uint16(0x0))
-	//assert.Equal(t, omciMsg.MessageType, StartSoftwareDownloadResponseType)
-	//assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	//assert.Equal(t, omciMsg.Length, uint16(40))
-	//
-	//msgLayer := packet.Layer(LayerTypeStartSoftwareDownloadResponse)
-	//
-	//assert.NotNil(t, msgLayer)
-	//
-	//response, ok2 := msgLayer.(*StartSoftwareDownloadResponse)
-	//assert.True(t, ok2)
-	//assert.NotNil(t, response)
-	//
-	//// Verify string output for message
-	//packetString := packet.String()
-	//assert.NotZero(t, len(packetString))
-}
-
-func TestStartSoftwareDownloadResponseSerialize(t *testing.T) {
-	// TODO: Need to complete implementation & debug this
-	//goodMessage := ""
-	//
-	//omciLayer := &OMCI{
-	//	TransactionID: 0x01,
-	//	MessageType:   StartSoftwareDownloadResponseType,
-	//	// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-	//	// Length:           0x28,						// Optional, defaults to 40 octets
-	//}
-	//request := &StartSoftwareDownloadResponse{
-	//	MeBasePacket: MeBasePacket{
-	//		EntityClass: OnuDataClassID,
-	//		// Default Instance ID is 0
-	//	},
-	//}
-	//// Test serialization back to former string
-	//var options gopacket.SerializeOptions
-	//options.FixLengths = true
-	//
-	//buffer := gopacket.NewSerializeBuffer()
-	//err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	//assert.NoError(t, err)
-	//
-	//outgoingPacket := buffer.Bytes()
-	//reconstituted := packetToString(outgoingPacket)
-	//assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-//                    1                   2                   3                   4
-//  1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4
-// 0008140a00070001		    - Download section, AR=0
-//                 cc       - Section 0xcc
-//                   01020304050607080910111213141516171819202122232425262728293031
-//                                                                                 00000028
-
-func TestDownloadSectionRequestDecodeNoResponseExpected(t *testing.T) {
-	goodMessage := "0008140a00070001cc0102030405060708091011121314151617181920212223242526272829303100000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, uint16(0x0008), omciMsg.TransactionID)
-	assert.Equal(t, DownloadSectionRequestType, omciMsg.MessageType)
-	assert.False(t, omciMsg.ResponseExpected)
-	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
-	assert.Equal(t, uint16(40), omciMsg.Length)
-
-	msgLayer := packet.Layer(LayerTypeDownloadSectionRequest)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*DownloadSectionRequest)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-	assert.Equal(t, uint8(0xcc), request.SectionNumber)
-	assert.Equal(t, MaxDownloadSectionLength, len(request.SectionData))
-
-	sectionData, genErr := stringToPacket("01020304050607080910111213141516171819202122232425262728293031")
-	assert.Nil(t, genErr)
-	assert.NotNil(t, sectionData)
-	assert.Equal(t, MaxDownloadSectionLength, len(sectionData))
-	assert.Equal(t, sectionData, request.SectionData[:])
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestDownloadSectionRequestDecodeResponseExpected(t *testing.T) {
-	goodMessage := "0008540a00070001cc0102030405060708091011121314151617181920212223242526272829303100000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, uint16(0x0008), omciMsg.TransactionID)
-	assert.Equal(t, DownloadSectionRequestWithResponseType, omciMsg.MessageType)
-	assert.True(t, omciMsg.ResponseExpected)
-	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
-	assert.Equal(t, uint16(40), omciMsg.Length)
-
-	msgLayer := packet.Layer(LayerTypeDownloadSectionRequest)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*DownloadSectionRequest)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-	assert.Equal(t, uint8(0xcc), request.SectionNumber)
-	assert.Equal(t, 31, len(request.SectionData))
-
-	sectionData, genErr := stringToPacket("01020304050607080910111213141516171819202122232425262728293031")
-	assert.Nil(t, genErr)
-	assert.NotNil(t, sectionData)
-	assert.Equal(t, MaxDownloadSectionLength, len(sectionData))
-	assert.Equal(t, sectionData, request.SectionData[:])
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestDownloadSectionRequestSerializeNoResponseExpected(t *testing.T) {
-	goodMessage := "0123140a00070000cc0102030405060708091011121314151617181920212223242526272829303100000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x0123,
-		MessageType:   DownloadSectionRequestType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	sectionData, genErr := stringToPacket("01020304050607080910111213141516171819202122232425262728293031")
-	assert.Nil(t, genErr)
-	assert.NotNil(t, sectionData)
-	assert.Equal(t, MaxDownloadSectionLength, len(sectionData))
-
-	request := &DownloadSectionRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass: me.SoftwareImageClassID,
-			// Default Instance ID is 0
-		},
-		SectionNumber: 0xcc,
-		SectionData:   sectionData,
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestDownloadSectionRequestSerializeNoResponsePartialDataExpected(t *testing.T) {
-	// If a small buffer is provided, serialize will now zero extend the baseline format
-	goodMessage := "0123140a00070000cc0102030405060708091011121314151617181920212223242526272829000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x0123,
-		MessageType:   DownloadSectionRequestType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	sectionData, genErr := stringToPacket("0102030405060708091011121314151617181920212223242526272829")
-	assert.Nil(t, genErr)
-	assert.NotNil(t, sectionData)
-	assert.Equal(t, MaxDownloadSectionLength-2, len(sectionData)) // Partial data buffer
-
-	request := &DownloadSectionRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass: me.SoftwareImageClassID,
-			// Default Instance ID is 0
-		},
-		SectionNumber: 0xcc,
-		SectionData:   sectionData,
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestDownloadSectionRequestSerializeResponseExpectedMethod1(t *testing.T) {
-	goodMessage := "2468540a00070000cc0102030405060708091011121314151617181920212223242526272829303100000028"
-
-	omciLayer := &OMCI{
-		TransactionID:    0x2468,
-		MessageType:      DownloadSectionRequestType, // or DownloadSectionRequestWithResponseType
-		ResponseExpected: true,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	sectionData, genErr := stringToPacket("01020304050607080910111213141516171819202122232425262728293031")
-	assert.Nil(t, genErr)
-	assert.NotNil(t, sectionData)
-	assert.Equal(t, MaxDownloadSectionLength, len(sectionData))
-
-	request := &DownloadSectionRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass: me.SoftwareImageClassID,
-			// Default Instance ID is 0
-		},
-		SectionNumber: 0xcc,
-		SectionData:   sectionData,
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestDownloadSectionRequestSerializeResponseExpectedMethod2(t *testing.T) {
-	goodMessage := "2468540a00070001cc0102030405060708091011121314151617181920212223242526272829303100000028"
-
-	// In this case, just use the request type with AR response requested already encoded
-	omciLayer := &OMCI{
-		TransactionID: 0x2468,
-		MessageType:   DownloadSectionRequestWithResponseType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	sectionData, genErr := stringToPacket("01020304050607080910111213141516171819202122232425262728293031")
-	assert.Nil(t, genErr)
-	assert.NotNil(t, sectionData)
-	assert.Equal(t, MaxDownloadSectionLength, len(sectionData))
-
-	request := &DownloadSectionRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.SoftwareImageClassID,
-			EntityInstance: 0x0001, // Default is zero, here we want image 1
-		},
-		SectionNumber: 0xcc,
-		SectionData:   sectionData,
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestDownloadSectionResponseDecode(t *testing.T) {
-	goodMessage := "0022340a00070001061f00000000000000000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0022))
-	assert.Equal(t, omciMsg.MessageType, DownloadSectionResponseType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeDownloadSectionResponse)
-
-	assert.NotNil(t, msgLayer)
-
-	response, ok2 := msgLayer.(*DownloadSectionResponse)
-	assert.True(t, ok2)
-	assert.NotNil(t, response)
-	assert.Equal(t, me.DeviceBusy, response.Result)
-	assert.Equal(t, byte(0x1f), response.SectionNumber)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestDownloadSectionResponseSerialize(t *testing.T) {
-	goodMessage := "0022340a00070001061f00000000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x0022,
-		MessageType:   DownloadSectionResponseType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &DownloadSectionResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.SoftwareImageClassID,
-			EntityInstance: 1,
-		},
-		Result:        me.DeviceBusy,
-		SectionNumber: 0x1f,
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestEndSoftwareDownloadRequestDecode(t *testing.T) {
-	//
-	// 8100 55 0a 0007 0001 ff92a226 000f4240 01 0001 00000000000000000000000000000000000000000000000028
-	//
-	goodMessage := "8100550a00070001ff92a226000f424001000100000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x8100))
-	assert.Equal(t, omciMsg.MessageType, EndSoftwareDownloadRequestType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeEndSoftwareDownloadRequest)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*EndSoftwareDownloadRequest)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-	assert.Equal(t, uint32(0xff92a226), request.CRC32)
-	assert.Equal(t, uint32(0x000f4240), request.ImageSize)
-	assert.Equal(t, byte(1), request.NumberOfInstances)
-	assert.Equal(t, 1, len(request.ImageInstances))
-	assert.Equal(t, uint16(1), request.ImageInstances[0])
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestEndSoftwareDownloadRequestSerialize(t *testing.T) {
-	// 8100 55 0a 0007 0001 ff92a226 000f4240 01 0001 00000000000000000000000000000000000000000000000028
-	goodMessage := "8100550a00070001ff92a226000f424001000100000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x8100,
-		MessageType:   EndSoftwareDownloadRequestType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &EndSoftwareDownloadRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.SoftwareImageClassID,
-			EntityInstance: 0x0001, // Default is zero, here we want image 1
-		},
-		CRC32:             0xff92a226,
-		ImageSize:         1000000,
-		NumberOfInstances: 1,
-		ImageInstances:    []uint16{1},
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestEndSoftwareDownloadResponseDecode(t *testing.T) {
-	// 8123 35 0a 0007 0001 06 0000000000000000000000000000000000000000000000000000000000000000000028
-	goodMessage := "8123350a00070001060000000000000000000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x8123))
-	assert.Equal(t, omciMsg.MessageType, EndSoftwareDownloadResponseType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeEndSoftwareDownloadResponse)
-	assert.NotNil(t, msgLayer)
-
-	response, ok2 := msgLayer.(*EndSoftwareDownloadResponse)
-	assert.True(t, ok2)
-	assert.NotNil(t, response)
-	assert.Equal(t, me.DeviceBusy, response.Result)
-	assert.Equal(t, byte(0), response.NumberOfInstances)
-	assert.Nil(t, response.MeResults)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestEndSoftwareDownloadResponseSerialize(t *testing.T) {
-	goodMessage := "8456350a00070000010000000000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x8456,
-		MessageType:   EndSoftwareDownloadResponseType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &EndSoftwareDownloadResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass: me.SoftwareImageClassID,
-			// Default is zero
-		},
-		Result:            me.ProcessingError,
-		NumberOfInstances: 0,
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestActivateSoftwareRequestDecode(t *testing.T) {
-	// TODO: Need to complete implementation & debug this
-	//goodMessage := "0000560a00070001000000000000000000000000000000000000000000000000000000000000000000000028"
-	//data, err := stringToPacket(goodMessage)
-	//assert.NoError(t, err)
-	//
-	//packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	//assert.NotNil(t, packet)
-	//
-	//omciLayer := packet.Layer(LayerTypeOMCI)
-	//assert.NotNil(t, omciLayer)
-	//
-	//omciMsg, ok := omciLayer.(*OMCI)
-	//assert.True(t, ok)
-	//assert.Equal(t, omciMsg.TransactionID, uint16(0x0))
-	//assert.Equal(t, omciMsg.MessageType, ActivateSoftwareRequestType)
-	//assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	//assert.Equal(t, omciMsg.Length, uint16(40))
-	//
-	//msgLayer := packet.Layer(LayerTypeActivateSoftwareRequest)
-	//assert.NotNil(t, msgLayer)
-	//
-	//request, ok2 := msgLayer.(*ActivateSoftwareRequest)
-	//assert.True(t, ok2)
-	//assert.NotNil(t, request)
-	//
-	//// Verify string output for message
-	//packetString := packet.String()
-	//assert.NotZero(t, len(packetString))
-}
-
-func TestActivateSoftwareRequestSerialize(t *testing.T) {
-	// TODO: Need to complete implementation & debug this
-	//goodMessage := "0000560a00070001000000000000000000000000000000000000000000000000000000000000000000000028"
-	//
-	//omciLayer := &OMCI{
-	//	TransactionID: 0x01,
-	//	MessageType:   ActivateSoftwareRequestType,
-	//	// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-	//	// Length:           0x28,						// Optional, defaults to 40 octets
-	//}
-	//request := &ActivateSoftwareRequest{
-	//	MeBasePacket: MeBasePacket{
-	//		EntityClass: OnuDataClassID,
-	//		// Default Instance ID is 0
-	//	},
-	//}
-	//// Test serialization back to former string
-	//var options gopacket.SerializeOptions
-	//options.FixLengths = true
-	//
-	//buffer := gopacket.NewSerializeBuffer()
-	//err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	//assert.NoError(t, err)
-	//
-	//outgoingPacket := buffer.Bytes()
-	//reconstituted := packetToString(outgoingPacket)
-	//assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestActivateSoftwareResponseDecode(t *testing.T) {
-	// TODO: Need to complete implementation & debug this
-	//goodMessage := ""
-	//data, err := stringToPacket(goodMessage)
-	//assert.NoError(t, err)
-	//
-	//packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	//assert.NotNil(t, packet)
-	//
-	//omciLayer := packet.Layer(LayerTypeOMCI)
-	//assert.NotNil(t, omciLayer)
-	//
-	//omciMsg, ok := omciLayer.(*OMCI)
-	//assert.True(t, ok)
-	//assert.Equal(t, omciMsg.TransactionID, uint16(0x0))
-	//assert.Equal(t, omciMsg.MessageType, ActivateSoftwareResponseType)
-	//assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	//assert.Equal(t, omciMsg.Length, uint16(40))
-	//
-	//msgLayer := packet.Layer(LayerTypeActivateSoftwareResponse)
-	//
-	//assert.NotNil(t, msgLayer)
-	//
-	//response, ok2 := msgLayer.(*ActivateSoftwareResponse)
-	//assert.True(t, ok2)
-	//assert.NotNil(t, response)
-	//
-	//// Verify string output for message
-	//packetString := packet.String()
-	//assert.NotZero(t, len(packetString))
-}
-
-func TestActivateSoftwareResponseSerialize(t *testing.T) {
-	// TODO: Need to complete implementation & debug this
-	//goodMessage := ""
-	//
-	//omciLayer := &OMCI{
-	//	TransactionID: 0x01,
-	//	MessageType:   ActivateSoftwareResponseType,
-	//	// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-	//	// Length:           0x28,						// Optional, defaults to 40 octets
-	//}
-	//request := &ActivateSoftwareResponse{
-	//	MeBasePacket: MeBasePacket{
-	//		EntityClass: OnuDataClassID,
-	//		// Default Instance ID is 0
-	//	},
-	//}
-	//// Test serialization back to former string
-	//var options gopacket.SerializeOptions
-	//options.FixLengths = true
-	//
-	//buffer := gopacket.NewSerializeBuffer()
-	//err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	//assert.NoError(t, err)
-	//
-	//outgoingPacket := buffer.Bytes()
-	//reconstituted := packetToString(outgoingPacket)
-	//assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestCommitSoftwareRequestDecode(t *testing.T) {
-	goodMessage := "0011570a00070001000000000000000000000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x11))
-	assert.Equal(t, omciMsg.MessageType, CommitSoftwareRequestType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeCommitSoftwareRequest)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*CommitSoftwareRequest)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-	assert.Equal(t, uint16(1), request.MeBasePacket.EntityInstance)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestCommitSoftwareRequestSerialize(t *testing.T) {
-	goodMessage := "0044570a00070001000000000000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x44,
-		MessageType:   CommitSoftwareRequestType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &CommitSoftwareRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.SoftwareImageClassID,
-			EntityInstance: 1, // Default Instance ID is 0
-		},
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestCommitSoftwareResponseDecode(t *testing.T) {
-	goodMessage := "00aa370a00070001060000000000000000000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0xaa))
-	assert.Equal(t, omciMsg.MessageType, CommitSoftwareResponseType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeCommitSoftwareResponse)
-
-	assert.NotNil(t, msgLayer)
-
-	response, ok2 := msgLayer.(*CommitSoftwareResponse)
-	assert.True(t, ok2)
-	assert.NotNil(t, response)
-	assert.Equal(t, uint16(1), response.MeBasePacket.EntityInstance)
-	assert.Equal(t, me.DeviceBusy, response.Result)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestCommitSoftwareResponseSerialize(t *testing.T) {
-	goodMessage := "8001370a00070001060000000000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x8001,
-		MessageType:   CommitSoftwareResponseType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &CommitSoftwareResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.SoftwareImageClassID,
-			EntityInstance: 1, // Default Instance ID is 0
-		},
-		Result: me.DeviceBusy,
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestMibResetResponseDecode(t *testing.T) {
-	goodMessage := "00012F0A00020000000000000000000000000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.MessageType, MibResetResponseType)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeMibResetResponse)
-
-	assert.NotNil(t, msgLayer)
-
-	response, ok2 := msgLayer.(*MibResetResponse)
-	assert.True(t, ok2)
-	assert.NotNil(t, response)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestMibResetResponseSerialize(t *testing.T) {
-	goodMessage := "00012F0A00020000000000000000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x01,
-		MessageType:   MibResetResponseType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &MibResetResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass: me.OnuDataClassID,
-			// Default Instance ID is 0
-		},
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestSynchronizeTimeRequestDecode(t *testing.T) {
-	goodMessage := "0109580a0100000007e20c0101301b0000000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.MessageType, SynchronizeTimeRequestType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeSynchronizeTimeRequest)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*SynchronizeTimeRequest)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-	assert.Equal(t, request.Year, uint16(2018))
-	assert.Equal(t, request.Month, uint8(12))
-	assert.Equal(t, request.Day, uint8(1))
-	assert.Equal(t, request.Hour, uint8(01))
-	assert.Equal(t, request.Minute, uint8(48))
-	assert.Equal(t, request.Second, uint8(27))
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestSynchronizeTimeRequestSerialize(t *testing.T) {
-	goodMessage := "0109580a0100000007e20c0101301b0000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x0109,
-		MessageType:   SynchronizeTimeRequestType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &SynchronizeTimeRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass: me.OnuGClassID,
-			// Default Instance ID is 0
-		},
-		Year:   uint16(2018),
-		Month:  uint8(12),
-		Day:    uint8(1),
-		Hour:   uint8(01),
-		Minute: uint8(48),
-		Second: uint8(27),
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestSynchronizeTimeResponseDecode(t *testing.T) {
-	goodMessage := "0109380a01000000000000000000000000000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.MessageType, SynchronizeTimeResponseType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeSynchronizeTimeResponse)
-	assert.NotNil(t, msgLayer)
-
-	response, ok2 := msgLayer.(*SynchronizeTimeResponse)
-	assert.True(t, ok2)
-	assert.NotNil(t, response)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestSynchronizeTimeResponseSerialize(t *testing.T) {
-	goodMessage := "0109380a01000000000000000000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x0109,
-		MessageType:   SynchronizeTimeResponseType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &SynchronizeTimeResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.OnuGClassID,
-			EntityInstance: uint16(0),
-		},
-		Result:         me.Success,
-		SuccessResults: uint8(0),
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestRebootRequestDecode(t *testing.T) {
-	goodMessage := "0001590a01000000010000000000000000000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0001))
-	assert.Equal(t, omciMsg.MessageType, RebootRequestType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeRebootRequest)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*RebootRequest)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-	assert.Equal(t, request.EntityClass, me.OnuGClassID)
-	assert.Equal(t, request.EntityInstance, uint16(0))
-	assert.Equal(t, request.RebootCondition, uint8(1))
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestRebootRequestSerialize(t *testing.T) {
-	goodMessage := "0001590a01000000020000000000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x0001,
-		MessageType:   RebootRequestType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &RebootRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass: me.OnuGClassID,
-			// Default Instance ID is 0
-		},
-		RebootCondition: uint8(2),
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestRebootResponseDecode(t *testing.T) {
-	goodMessage := "023c390a01000000000000000000000000000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x023c))
-	assert.Equal(t, omciMsg.MessageType, RebootResponseType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeRebootResponse)
-	assert.NotNil(t, msgLayer)
-
-	response, ok2 := msgLayer.(*RebootResponse)
-	assert.True(t, ok2)
-	assert.NotNil(t, response)
-	assert.Equal(t, response.EntityClass, me.OnuGClassID)
-	assert.Equal(t, response.EntityInstance, uint16(0))
-	assert.Equal(t, response.Result, me.Success)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestRebootResponseSerialize(t *testing.T) {
-	goodMessage := "023c390a01000000060000000000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x023c,
-		MessageType:   RebootResponseType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &RebootResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.OnuGClassID,
-			EntityInstance: uint16(0),
-		},
-		Result: me.DeviceBusy,
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestGetNextRequestDecode(t *testing.T) {
-	goodMessage := "285e5a0a00ab0202040000010000000000000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x285e))
-	assert.Equal(t, omciMsg.MessageType, GetNextRequestType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeGetNextRequest)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*GetNextRequest)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-	assert.Equal(t, request.EntityClass, me.ExtendedVlanTaggingOperationConfigurationDataClassID)
-	assert.Equal(t, request.EntityInstance, uint16(0x0202))
-	assert.Equal(t, request.AttributeMask, uint16(0x0400))
-	assert.Equal(t, request.SequenceNumber, uint16(1))
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestGetNextRequestSerialize(t *testing.T) {
-	goodMessage := "285e5a0a00ab0202040000010000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x285e,
-		MessageType:   GetNextRequestType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &GetNextRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
-			EntityInstance: uint16(0x0202),
-		},
-		AttributeMask:  uint16(0x0400),
-		SequenceNumber: uint16(1),
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestGetNextResponseDecode(t *testing.T) {
-	goodMessage := "285e3a0a00ab0202000400080334000000000000000000000000000000000000000000000000000000000028"
-
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x285e))
-	assert.Equal(t, omciMsg.MessageType, GetNextResponseType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeGetNextResponse)
-	assert.NotNil(t, msgLayer)
-
-	vlanOpTable := []byte{0x08, 0x03, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
-
-	response, ok2 := msgLayer.(*GetNextResponse)
-	assert.True(t, ok2)
-	assert.NotNil(t, response)
-	assert.Equal(t, me.ExtendedVlanTaggingOperationConfigurationDataClassID, response.EntityClass)
-	assert.Equal(t, uint16(0x0202), response.EntityInstance)
-	assert.Equal(t, me.Success, response.Result)
-	assert.Equal(t, uint16(0x0400), response.AttributeMask)
-
-	// For GetNextResponse frames, caller is responsible for trimming last packet to remaining
-	// size
-	expectedOctets := 16
-	value := response.Attributes["ReceivedFrameVlanTaggingOperationTable"]
-	assert.Equal(t, vlanOpTable, value.([]byte)[:expectedOctets])
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestGetNextResponseSerialize(t *testing.T) {
-	goodMessage := "285e3a0a00ab0202000400080334000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x285e,
-		MessageType:   GetNextResponseType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	vlanOpTable := []byte{0x08, 0x03, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
-
-	request := &GetNextResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
-			EntityInstance: uint16(0x0202),
-		},
-		Result:        me.Success,
 		AttributeMask: uint16(0x0400),
-		Attributes:    me.AttributeValueMap{"ReceivedFrameVlanTaggingOperationTable": vlanOpTable},
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-// TODO: Create request/response tests for all of the following types -> SetTable
-
-func TestAlarmNotificationDecode(t *testing.T) {
-	goodMessage := "0000100a000b0104800000000000000000000000000000000000000000000000000000000000000500000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0))
-	assert.Equal(t, omciMsg.MessageType, AlarmNotificationType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeAlarmNotification)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*AlarmNotificationMsg)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-	assert.Equal(t, request.EntityClass, me.PhysicalPathTerminationPointEthernetUniClassID)
-	assert.Equal(t, request.EntityInstance, uint16(0x104))
-	assert.Equal(t, request.AlarmBitmap, [28]byte{
-		0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	})
-	assert.Equal(t, request.AlarmSequenceNumber, byte(5))
-
-	// Active/Clear tests
-	active, err2 := request.IsAlarmActive(0)
-	clear, err3 := request.IsAlarmClear(0)
-	assert.Nil(t, err2)
-	assert.Nil(t, err3)
-	assert.True(t, active)
-	assert.False(t, clear)
-
-	// Active/Clear for undefined alarm bits
-	active, err2 = request.IsAlarmActive(1)
-	clear, err3 = request.IsAlarmClear(1)
-	assert.NotNil(t, err2)
-	assert.NotNil(t, err3)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestInvalidClassAlarmNotificationDecode(t *testing.T) {
-	// Choosing GalEthernetProfile (272) since it does not support alarms, show we should
-	// file the decode
-	badMessage := "0000100a01100104800000000000000000000000000000000000000000000000000000000000000500000028"
-	data, err := stringToPacket(badMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0))
-	assert.Equal(t, omciMsg.MessageType, AlarmNotificationType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeAlarmNotification)
-	assert.Nil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*AlarmNotificationMsg)
-	assert.False(t, ok2)
-	assert.Nil(t, request)
-}
-
-func TestUnknownsMeAlarmNotificationDecode(t *testing.T) {
-	// Choosing class ID 22 since it is in the G.988 class ID space and is reserved
-	goodMessage := "0000100a00160104800000000000000000000000000000000000000000000000000000000000000500000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0))
-	assert.Equal(t, omciMsg.MessageType, AlarmNotificationType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeAlarmNotification)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*AlarmNotificationMsg)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-	assert.Equal(t, request.EntityClass, me.ClassID(22))
-	assert.Equal(t, request.EntityInstance, uint16(0x104))
-	assert.Equal(t, request.AlarmBitmap, [28]byte{
-		0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	})
-	assert.Equal(t, request.AlarmSequenceNumber, byte(5))
-}
-
-func TestVendorSpecificAlarmNotificationDecode(t *testing.T) {
-	// Choosing class ID 255 since it is in the first vendor specific class ID space
-	goodMessage := "0000100a00FF0104800000000000000000000000000000000000000000000000000000000000000500000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0))
-	assert.Equal(t, omciMsg.MessageType, AlarmNotificationType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeAlarmNotification)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*AlarmNotificationMsg)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-	assert.Equal(t, request.EntityClass, me.ClassID(255))
-	assert.Equal(t, request.EntityInstance, uint16(0x104))
-	assert.Equal(t, request.AlarmBitmap, [28]byte{
-		0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	})
-	assert.Equal(t, request.AlarmSequenceNumber, byte(5))
-}
-
-func TestAlarmNotificationSerialize(t *testing.T) {
-	goodMessage := "0000100a000b0104800000000000000000000000000000000000000000000000000000000000000500000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0,
-		MessageType:   AlarmNotificationType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &AlarmNotificationMsg{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.PhysicalPathTerminationPointEthernetUniClassID,
-			EntityInstance: uint16(0x104),
-		},
-		AlarmBitmap: [28]byte{
-			0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		},
-		AlarmSequenceNumber: byte(5),
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestAttributeValueChangeDecode(t *testing.T) {
-	goodMessage := "0000110a0007000080004d4c2d33363236000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0))
-	assert.Equal(t, omciMsg.MessageType, AttributeValueChangeType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeAttributeValueChange)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*AttributeValueChangeMsg)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-	assert.Equal(t, request.AttributeMask, uint16(0x8000))
-	assert.Equal(t, request.EntityClass, me.SoftwareImageClassID)
-	assert.Equal(t, request.EntityInstance, uint16(0))
-	assert.Equal(t, request.Attributes["Version"], []byte{
-		0x4d, 0x4c, 0x2d, 0x33, 0x36, 0x32, 0x36,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestAttributeValueChangeSerialize(t *testing.T) {
-	goodMessage := "0000110a0007000080004d4c2d33363236000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0,
-		MessageType:   AttributeValueChangeType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &AttributeValueChangeMsg{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.SoftwareImageClassID,
-			EntityInstance: uint16(0),
-		},
-		AttributeMask: uint16(0x8000),
 		Attributes: me.AttributeValueMap{
-			"Version": []byte{
-				0x4d, 0x4c, 0x2d, 0x33, 0x36, 0x32, 0x36,
-				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-			},
-		},
+			"ImageHash": toOctets("AAECAwQFBgcICQoLDA0ODw==")}, // 0->f octets
 	}
 	// Test serialization back to former string
 	var options gopacket.SerializeOptions
@@ -3000,1541 +313,3 @@
 	reconstituted := packetToString(outgoingPacket)
 	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
 }
-
-func TestJira3769(t *testing.T) {
-	// VOL-3769.  Error parsing get response with processing error and large mask
-	sampleMessage := "035e290a0101000001FFFC000000000000000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(sampleMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x035e))
-	assert.Equal(t, omciMsg.MessageType, GetResponseType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	// before bugfix for this JIRA, the following call returned 'nil'  Failure was
-	// occurring before this at during getResponse decoding.
-	msgLayer := packet.Layer(LayerTypeGetResponse)
-	assert.NotNil(t, msgLayer)
-
-	response, ok2 := msgLayer.(*GetResponse)
-	assert.True(t, ok2)
-	assert.NotNil(t, response)
-	assert.Equal(t, response.Result, me.ProcessingError)
-	assert.Equal(t, response.AttributeMask, uint16(0xFFFC))
-}
-
-func TestJira3863(t *testing.T) {
-	goodMessage := "81a9240a013880010700000000000000000000000000000000000000000000000000000000000000000000283f73ddea"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.NotNil(t, omciMsg)
-
-	msgLayer := packet.Layer(LayerTypeCreateResponse)
-	assert.NotNil(t, msgLayer)
-
-	// FEC PM ME not in class map so the following was failing (ok2 false)
-	response, ok2 := msgLayer.(*CreateResponse)
-	assert.True(t, ok2)
-	assert.NotNil(t, response)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestExtendedGetRequestDecode(t *testing.T) {
-	//ONU-2G: 257
-	goodMessage := "035e490b010100000002fffc"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x035e))
-	assert.Equal(t, omciMsg.MessageType, GetRequestType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, ExtendedIdent)
-	assert.Equal(t, omciMsg.Length, uint16(2))
-
-	msgLayer := packet.Layer(LayerTypeGetRequest)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*GetRequest)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-
-	//ONU-2G: 257
-	assert.Equal(t, me.Onu2GClassID, request.EntityClass)
-	assert.Equal(t, uint16(0), request.EntityInstance)
-	assert.Equal(t, uint16(0xfffc), request.AttributeMask)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestExtendedGetRequestDecodeTruncated(t *testing.T) {
-	goodMessage := "035e490b010100000002ff"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	failure := packet.ErrorLayer()
-	assert.NotNil(t, failure)
-
-	decodeFailure, ok := failure.(*gopacket.DecodeFailure)
-	assert.NotNil(t, decodeFailure)
-	assert.True(t, ok)
-	assert.NotNil(t, decodeFailure.String())
-	assert.True(t, len(decodeFailure.String()) > 0)
-
-	metadata := packet.Metadata()
-	assert.NotNil(t, metadata)
-	assert.True(t, metadata.Truncated)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestExtendedGetRequestSerialize(t *testing.T) {
-	goodMessage := "035e490b010100000002fffc"
-
-	omciLayer := &OMCI{
-		TransactionID:    0x035e,
-		MessageType:      GetRequestType,
-		DeviceIdentifier: ExtendedIdent,
-		// Length parameter is optional for Extended message format serialization
-		// and if present it will be overwritten during the serialization with the
-		// actual value.
-	}
-	request := &GetRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.Onu2GClassID,
-			EntityInstance: uint16(0),
-			Extended:       true,
-		},
-		AttributeMask: uint16(0xfffc),
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestExtendedGetResponseDecode(t *testing.T) {
-	attrDef, omciErr := me.GetAttributesDefinitions(me.Onu2GClassID)
-	assert.NotNil(t, attrDef)
-	assert.NotNil(t, omciErr)
-	assert.Equal(t, omciErr.StatusCode(), me.Success)
-
-	attributes := []interface{}{
-		toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAA="), //  1: MultiByteField - "EquipmentId"  (20 zeros)
-		byte(0xb4),                               //  2: ByteField   - "OpticalNetworkUnitManagementAndControlChannelOmccVersion"
-		uint16(0x1234),                           //  3: Uint16Field - "VendorProductCode"
-		byte(1),                                  //  4: ByteField   - "SecurityCapability"
-		byte(1),                                  //  5: ByteField   - "SecurityMode"
-		uint16(0x5678),                           //  6: Uint16Field - "TotalPriorityQueueNumber"
-		byte(0x44),                               //  7: ByteField   - "TotalTrafficSchedulerNumber"
-		byte(1),                                  //  8: ByteField   - "Deprecated"
-		uint16(0x55aa),                           //  9: Uint16Field - "TotalGemPortIdNumber"
-		uint32(0xC4108011),                       // 10: Uint32Field - "Sysuptime"
-		uint16(0x6),                              // 11: Uint16Field - "ConnectivityCapability"
-		byte(6),                                  // 12: ByteField   - "CurrentConnectivityMode"
-		uint16(2),                                // 13: Uint16Field - "QualityOfServiceQosConfigurationFlexibility"
-		uint16(0x1234),                           // 14: Uint16Field - "PriorityQueueScaleFactor"
-	}
-	attributeData := make([]byte, 0)
-
-	// Walk through all attributes and encode them
-	for _, value := range attributes {
-		//attrDef, err := meDef.GetAttributeByIndex(index)
-		var buf []byte
-		u8, ok := value.(byte)
-		if ok {
-			buf = []byte{u8}
-		} else {
-			u16, ok := value.(uint16)
-			if ok {
-				buf = make([]byte, 2)
-				binary.BigEndian.PutUint16(buf, u16)
-			} else {
-				u32, ok := value.(uint32)
-				if ok {
-					buf = make([]byte, 4)
-					binary.BigEndian.PutUint32(buf, u32)
-				} else {
-					bytes, ok := value.([]byte)
-					if ok {
-						buf = bytes
-					} else {
-						assert.True(t, false) // Unknown attribute type
-					}
-				}
-			}
-		}
-		attributeData = append(attributeData, buf...)
-	}
-	attributeMask := 0xfffc
-	msgLength := len(attributeData) + 7
-	// Results is 0 ("00"), and the two optional attribute masks are 0 ("00000000") as well
-	goodMessage := "035e290b01010000" + fmt.Sprintf("%04x", msgLength) +
-		"00" + fmt.Sprintf("%04x", attributeMask) + "00000000" + packetToString(attributeData)
-
-	data, err := stringToPacket(goodMessage)
-	assert.NotNil(t, data)
-	assert.Nil(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x035e))
-	assert.Equal(t, omciMsg.MessageType, GetResponseType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, ExtendedIdent)
-	assert.Equal(t, omciMsg.Length, uint16(msgLength))
-
-	msgLayer := packet.Layer(LayerTypeGetResponse)
-	assert.NotNil(t, msgLayer)
-
-	response, ok2 := msgLayer.(*GetResponse)
-	assert.True(t, ok2)
-	assert.NotNil(t, response)
-	assert.Equal(t, response.Result, me.Success)
-	assert.Equal(t, response.AttributeMask, uint16(attributeMask))
-	assert.Equal(t, response.FailedAttributeMask, uint16(0))
-	assert.Equal(t, response.UnsupportedAttributeMask, uint16(0))
-
-	assert.Equal(t, response.Attributes["EquipmentId"], toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAA="))
-	assert.Equal(t, response.Attributes["OpticalNetworkUnitManagementAndControlChannelOmccVersion"], byte(0xb4)) //  )
-	assert.Equal(t, response.Attributes["VendorProductCode"], uint16(0x1234))
-	assert.Equal(t, response.Attributes["SecurityCapability"], byte(1))
-	assert.Equal(t, response.Attributes["SecurityMode"], byte(1))
-	assert.Equal(t, response.Attributes["TotalPriorityQueueNumber"], uint16(0x5678))
-	assert.Equal(t, response.Attributes["TotalTrafficSchedulerNumber"], byte(0x44))
-	assert.Equal(t, response.Attributes["Deprecated"], byte(1))
-	assert.Equal(t, response.Attributes["TotalGemPortIdNumber"], uint16(0x55aa))
-	assert.Equal(t, response.Attributes["Sysuptime"], uint32(0xC4108011))
-	assert.Equal(t, response.Attributes["ConnectivityCapability"], uint16(0x6))
-	assert.Equal(t, response.Attributes["CurrentConnectivityMode"], byte(6))
-	assert.Equal(t, response.Attributes["QualityOfServiceQosConfigurationFlexibility"], uint16(2))
-	assert.Equal(t, response.Attributes["PriorityQueueScaleFactor"], uint16(0x1234))
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestExtendedGetResponseSerialize(t *testing.T) {
-	goodMessage := "035e290b01010000003100fffc" +
-		"000000000000000000000000000000000000000000000000" +
-		"b4123401015678440155aac410801100060600021234"
-
-	omciLayer := &OMCI{
-		TransactionID:    0x035e,
-		MessageType:      GetResponseType,
-		DeviceIdentifier: ExtendedIdent,
-		// Length parameter is optional for Extended message format serialization
-		// and if present it will be overwritten during the serialization with the
-		// actual value.
-	}
-	request := &GetResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.Onu2GClassID,
-			EntityInstance: uint16(0),
-			Extended:       true,
-		},
-		Result:        0,
-		AttributeMask: uint16(0xfffc),
-		Attributes: me.AttributeValueMap{
-			"EquipmentId": toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
-			"OpticalNetworkUnitManagementAndControlChannelOmccVersion": byte(0xb4),
-			"VendorProductCode":                           uint16(0x1234),
-			"SecurityCapability":                          byte(1),
-			"SecurityMode":                                byte(1),
-			"TotalPriorityQueueNumber":                    uint16(0x5678),
-			"TotalTrafficSchedulerNumber":                 byte(0x44),
-			"Deprecated":                                  byte(1),
-			"TotalGemPortIdNumber":                        uint16(0x55aa),
-			"Sysuptime":                                   uint32(0xC4108011),
-			"ConnectivityCapability":                      uint16(0x6),
-			"CurrentConnectivityMode":                     byte(6),
-			"QualityOfServiceQosConfigurationFlexibility": uint16(2),
-			"PriorityQueueScaleFactor":                    uint16(0x1234),
-		},
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-//                    1                   2                   3                   4
-//  1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4
-// 0008140a00070001		    - Download section, AR=0
-//                 cc       - Section 0xcc
-//                   01020304050607080910111213141516171819202122232425262728293031
-//                                                                                 00000028
-func TestExtendedDownloadSectionRequestDecodeNoResponseExpected(t *testing.T) {
-	goodMessage := "0008140b00070001"
-	payloadFragment := "01020304050607080910111213141516171819202122232425"
-	payloadTotal := payloadFragment + payloadFragment + payloadFragment + payloadFragment +
-		payloadFragment + payloadFragment + payloadFragment + payloadFragment
-	sectionNumber := 0x88
-	length := 1 + (8 * 25)
-	hdr := fmt.Sprintf("%04x%02x", length, sectionNumber)
-	goodMessage += hdr + payloadTotal
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-	assert.Nil(t, packet.ErrorLayer())
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, uint16(0x0008), omciMsg.TransactionID)
-	assert.Equal(t, DownloadSectionRequestType, omciMsg.MessageType)
-	assert.False(t, omciMsg.ResponseExpected)
-	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
-	assert.Equal(t, uint16(length), omciMsg.Length)
-
-	msgLayer := packet.Layer(LayerTypeDownloadSectionRequest)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*DownloadSectionRequest)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-	assert.Equal(t, uint8(sectionNumber), request.SectionNumber)
-	assert.Equal(t, length-1, len(request.SectionData))
-
-	data, err = stringToPacket(payloadTotal)
-	assert.NoError(t, err)
-	assert.Equal(t, data, request.SectionData[:])
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestExtendedDownloadSectionRequestDecodeResponseExpected(t *testing.T) {
-	goodMessage := "0008540b00070001"
-	payloadFragment := "01020304050607080910111213141516171819202122232425"
-	payloadTotal := payloadFragment + payloadFragment + payloadFragment + payloadFragment +
-		payloadFragment + payloadFragment + payloadFragment + payloadFragment +
-		payloadFragment + payloadFragment + payloadFragment + payloadFragment +
-		payloadFragment + payloadFragment + payloadFragment + payloadFragment +
-		payloadFragment + payloadFragment + payloadFragment + payloadFragment
-	sectionNumber := 0x88
-	length := 1 + (20 * 25)
-	hdr := fmt.Sprintf("%04x%02x", length, sectionNumber)
-	goodMessage += hdr + payloadTotal
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-	assert.Nil(t, packet.ErrorLayer())
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, uint16(0x0008), omciMsg.TransactionID)
-	assert.Equal(t, DownloadSectionRequestWithResponseType, omciMsg.MessageType)
-	assert.True(t, omciMsg.ResponseExpected)
-	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
-	assert.Equal(t, uint16(length), omciMsg.Length)
-
-	msgLayer := packet.Layer(LayerTypeDownloadSectionRequest)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*DownloadSectionRequest)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-	assert.Equal(t, uint8(sectionNumber), request.SectionNumber)
-	assert.Equal(t, length-1, len(request.SectionData))
-
-	data, err = stringToPacket(payloadTotal)
-	assert.NoError(t, err)
-	assert.Equal(t, data, request.SectionData)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestExtendedDownloadSectionRequestDecodeTruncated(t *testing.T) {
-	goodMessage := "0008540b000700010000"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	failure := packet.ErrorLayer()
-	assert.NotNil(t, failure)
-
-	decodeFailure, ok := failure.(*gopacket.DecodeFailure)
-	assert.NotNil(t, decodeFailure)
-	assert.True(t, ok)
-	assert.NotNil(t, decodeFailure.String())
-	assert.True(t, len(decodeFailure.String()) > 0)
-
-	metadata := packet.Metadata()
-	assert.NotNil(t, metadata)
-	assert.True(t, metadata.Truncated)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestExtendedDownloadSectionRequestSerializeNoResponseExpected(t *testing.T) {
-	goodMessage := "0123140b00070001"
-	payloadFragment := "01020304050607080910111213141516171819202122232425"
-	payloadTotal := payloadFragment + payloadFragment + payloadFragment + payloadFragment +
-		payloadFragment + payloadFragment + payloadFragment + payloadFragment
-	sectionNumber := 0x84
-	length := 1 + (8 * 25)
-	hdr := fmt.Sprintf("%04x%02x", length, sectionNumber)
-	goodMessage += hdr + payloadTotal
-
-	omciLayer := &OMCI{
-		TransactionID:    0x0123,
-		MessageType:      DownloadSectionRequestType,
-		DeviceIdentifier: ExtendedIdent,
-	}
-	sectionData, genErr := stringToPacket(payloadTotal)
-	assert.Nil(t, genErr)
-	assert.NotNil(t, sectionData)
-	assert.Equal(t, len(payloadTotal)/2, len(sectionData))
-
-	request := &DownloadSectionRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.SoftwareImageClassID,
-			EntityInstance: uint16(1),
-			Extended:       true,
-		},
-		SectionNumber: byte(sectionNumber),
-		SectionData:   sectionData,
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestExtendedDownloadSectionRequestSerializeResponseExpectedMethod1(t *testing.T) {
-	goodMessage := "2468540b00070001"
-	payloadFragment := "01020304050607080910111213141516171819202122232425"
-	payloadTotal := payloadFragment + payloadFragment + payloadFragment + payloadFragment +
-		payloadFragment + payloadFragment + payloadFragment + payloadFragment
-	sectionNumber := 0x84
-	length := 1 + (8 * 25)
-	hdr := fmt.Sprintf("%04x%02x", length, sectionNumber)
-	goodMessage += hdr + payloadTotal
-
-	omciLayer := &OMCI{
-		TransactionID:    0x2468,
-		MessageType:      DownloadSectionRequestType, // or DownloadSectionRequestWithResponseType
-		ResponseExpected: true,
-		DeviceIdentifier: ExtendedIdent,
-	}
-	sectionData, genErr := stringToPacket(payloadTotal)
-	assert.Nil(t, genErr)
-	assert.NotNil(t, sectionData)
-	assert.Equal(t, len(payloadTotal)/2, len(sectionData))
-
-	request := &DownloadSectionRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.SoftwareImageClassID,
-			EntityInstance: uint16(1),
-			Extended:       true,
-		},
-		SectionNumber: byte(sectionNumber),
-		SectionData:   sectionData,
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestExtendedDownloadSectionRequestSerializeResponseExpectedMethod2(t *testing.T) {
-	goodMessage := "2468540b00070001"
-	payloadFragment := "01020304050607080910111213141516171819202122232425"
-	payloadTotal := payloadFragment + payloadFragment + payloadFragment + payloadFragment +
-		payloadFragment + payloadFragment + payloadFragment + payloadFragment
-	sectionNumber := 0x84
-	length := 1 + (8 * 25)
-	hdr := fmt.Sprintf("%04x%02x", length, sectionNumber)
-	goodMessage += hdr + payloadTotal
-
-	// In this case, just use the request type with AR response requested already encoded
-	omciLayer := &OMCI{
-		TransactionID:    0x2468,
-		MessageType:      DownloadSectionRequestWithResponseType,
-		ResponseExpected: true,
-		DeviceIdentifier: ExtendedIdent,
-	}
-	sectionData, genErr := stringToPacket(payloadTotal)
-	assert.Nil(t, genErr)
-	assert.NotNil(t, sectionData)
-	assert.Equal(t, len(payloadTotal)/2, len(sectionData))
-
-	request := &DownloadSectionRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.SoftwareImageClassID,
-			EntityInstance: 0x0001, // Default is zero, here we want image 1
-			Extended:       true,
-		},
-		SectionNumber: byte(sectionNumber),
-		SectionData:   sectionData,
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestExtendedDownloadSectionResponseDecode(t *testing.T) {
-	goodMessage := "0022340b000700010002061f"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0022))
-	assert.Equal(t, omciMsg.MessageType, DownloadSectionResponseType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, ExtendedIdent)
-	assert.Equal(t, uint16(2), omciMsg.Length)
-
-	msgLayer := packet.Layer(LayerTypeDownloadSectionResponse)
-	assert.NotNil(t, msgLayer)
-
-	response, ok2 := msgLayer.(*DownloadSectionResponse)
-	assert.True(t, ok2)
-	assert.NotNil(t, response)
-	assert.Equal(t, me.DeviceBusy, response.Result)
-	assert.Equal(t, byte(0x1f), response.SectionNumber)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestExtendedDownloadSectionResponseDecodeTruncated(t *testing.T) {
-	goodMessage := "0022340b00070001000106"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	failure := packet.ErrorLayer()
-	assert.NotNil(t, failure)
-
-	decodeFailure, ok := failure.(*gopacket.DecodeFailure)
-	assert.NotNil(t, decodeFailure)
-	assert.True(t, ok)
-	assert.NotNil(t, decodeFailure.String())
-	assert.True(t, len(decodeFailure.String()) > 0)
-
-	metadata := packet.Metadata()
-	assert.NotNil(t, metadata)
-	assert.True(t, metadata.Truncated)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestExtendedDownloadSectionResponseSerialize(t *testing.T) {
-	goodMessage := "0022340b000700010002061f"
-
-	omciLayer := &OMCI{
-		TransactionID:    0x0022,
-		MessageType:      DownloadSectionResponseType,
-		DeviceIdentifier: ExtendedIdent,
-	}
-	request := &DownloadSectionResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.SoftwareImageClassID,
-			EntityInstance: 1,
-			Extended:       true,
-		},
-		Result:        me.DeviceBusy,
-		SectionNumber: 0x1f,
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestGenericTestResultDecode(t *testing.T) {
-	// ONU-G ME for this test with just made up data
-	payload := "1234567890123456789012345678901234567890123456789012345678901234"
-	goodMessage := "00001b0a01000000" + payload + "00000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0000))
-	assert.Equal(t, omciMsg.MessageType, TestResultType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, uint16(40), omciMsg.Length)
-
-	msgLayer := packet.Layer(LayerTypeTestResult)
-	assert.NotNil(t, msgLayer)
-
-	// This is a generic struct since we do not do detailed decode
-	generic, ok2 := msgLayer.(*TestResultNotification)
-	assert.True(t, ok2)
-	assert.NotNil(t, generic)
-	assert.NotNil(t, generic.MeBasePacket.Payload) // Next three all same data
-	assert.NotNil(t, generic.Payload)
-	assert.NotNil(t, generic.TestResults())
-
-	base := generic.MeBasePacket
-	assert.Equal(t, me.OnuGClassID, base.EntityClass)
-	assert.Equal(t, uint16(0), base.EntityInstance)
-
-	// For the generic Test Result, get the payload data which is all the data in
-	// the test notification past the Entity Instance value.
-	payloadData, payloadErr := stringToPacket(payload)
-	assert.NotNil(t, payloadData)
-	assert.NoError(t, payloadErr)
-	assert.Equal(t, payloadData, base.Payload)
-	assert.Equal(t, payloadData, generic.Payload)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestOpticalLineSupervisionTestResultDecode(t *testing.T) {
-	// ANI-G ME for this test with just made up data
-	payload := "010034" + "030067" + "050091" + "090034" + "0c0067" + "8901" + "000000000000000000000000000000"
-	goodMessage := "00001b0a01078001" + payload + "00000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x0000))
-	assert.Equal(t, omciMsg.MessageType, TestResultType)
-	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
-	assert.Equal(t, uint16(40), omciMsg.Length)
-
-	msgLayer := packet.Layer(LayerTypeTestResult)
-	assert.NotNil(t, msgLayer)
-
-	// This is a optical line test results
-	optical, ok2 := msgLayer.(*OpticalLineSupervisionTestResult)
-	assert.True(t, ok2)
-	assert.NotNil(t, optical)
-
-	// Get the Managed Entity class ID and instance ID from the base packet
-	base := optical.MeBasePacket
-	assert.Equal(t, me.AniGClassID, base.EntityClass)
-	assert.Equal(t, uint16(0x8001), base.EntityInstance)
-
-	assert.Equal(t, uint8(1), optical.PowerFeedVoltageType)
-	assert.Equal(t, uint16(0x34), optical.PowerFeedVoltage)
-
-	assert.Equal(t, uint8(3), optical.ReceivedOpticalPowerType)
-	assert.Equal(t, uint16(0x67), optical.ReceivedOpticalPower)
-
-	assert.Equal(t, uint8(5), optical.MeanOpticalLaunchType)
-	assert.Equal(t, uint16(0x91), optical.MeanOpticalLaunch)
-
-	assert.Equal(t, uint8(9), optical.LaserBiasCurrentType)
-	assert.Equal(t, uint16(0x34), optical.LaserBiasCurrent)
-
-	assert.Equal(t, uint8(12), optical.TemperatureType)
-	assert.Equal(t, uint16(0x67), optical.Temperature)
-
-	assert.Equal(t, uint16(0x8901), optical.GeneralPurposeBuffer)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestGenericTestResultSerialize(t *testing.T) {
-	payload := "1234567891234567890123456789012345678901234567890123456789012345"
-	goodMessage := "00001b0a01000000" + payload + "00000028"
-
-	omciLayer := &OMCI{
-		// TransactionID: 0x0c,						// Optional for notifications since TID always 0x0000
-		MessageType: TestResultType,
-		// DeviceIdentifier: omci.BaselineIdent,    // Optional, defaults to Baseline
-		// Length:           0x28,					// Optional, defaults to 40 octets
-	}
-	data, derr := stringToPacket(payload)
-	assert.NoError(t, derr)
-
-	request := &TestResultNotification{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.OnuGClassID,
-			EntityInstance: uint16(0),
-		},
-		Payload: data,
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestOpticalLineSupervisionTestResultSerialize(t *testing.T) {
-	// ANI-G ME for this test with just made up data
-	payload := "010034" + "030067" + "050091" + "090034" + "0c0067" + "8901" + "000000000000000000000000000000"
-	goodMessage := "00001b0a01078001" + payload + "00000028"
-
-	omciLayer := &OMCI{
-		// TransactionID: 0x0c,						// Optional for notifications since TID always 0x0000
-		MessageType: TestResultType,
-		// DeviceIdentifier: omci.BaselineIdent,    // Optional, defaults to Baseline
-		// Length:           0x28,					// Optional, defaults to 40 octets
-	}
-	request := &OpticalLineSupervisionTestResult{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.AniGClassID,
-			EntityInstance: uint16(0x8001),
-		},
-		PowerFeedVoltageType:     uint8(1),
-		PowerFeedVoltage:         uint16(0x34),
-		ReceivedOpticalPowerType: uint8(3),
-		ReceivedOpticalPower:     uint16(0x67),
-		MeanOpticalLaunchType:    uint8(5),
-		MeanOpticalLaunch:        uint16(0x91),
-		LaserBiasCurrentType:     uint8(9),
-		LaserBiasCurrent:         uint16(0x34),
-		TemperatureType:          uint8(12),
-		Temperature:              uint16(0x67),
-		GeneralPurposeBuffer:     uint16(0x8901),
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestGenericTestRequestDecode(t *testing.T) {
-	// ONU-G ME for this test with just made up data
-	payload := "1234567890523456789012345678901234567890123456789012345678901234"
-	goodMessage := "0123520a01000000" + payload + "00000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, uint16(0x0123), omciMsg.TransactionID)
-	assert.Equal(t, TestRequestType, omciMsg.MessageType)
-	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
-	assert.Equal(t, uint16(40), omciMsg.Length)
-
-	msgLayer := packet.Layer(LayerTypeTestRequest)
-	assert.NotNil(t, msgLayer)
-
-	// This is a generic struct since we do not do detailed decode
-	generic, ok2 := msgLayer.(*TestRequest)
-	assert.True(t, ok2)
-	assert.NotNil(t, generic)
-	assert.NotNil(t, generic.MeBasePacket.Payload) // Next three all same data
-	assert.NotNil(t, generic.Payload)
-	assert.NotNil(t, generic.TestRequest())
-
-	base := generic.MeBasePacket
-	assert.Equal(t, me.OnuGClassID, base.EntityClass)
-	assert.Equal(t, uint16(0), base.EntityInstance)
-
-	// For the generic Test Result, get the payload data which is all the data in
-	// the test notification past the Entity Instance value.
-	payloadData, payloadErr := stringToPacket(payload)
-	assert.NotNil(t, payloadData)
-	assert.NoError(t, payloadErr)
-	assert.Equal(t, payloadData, base.Payload)
-	assert.Equal(t, payloadData, generic.Payload)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestOpticalLineSupervisionTestRequestDecode(t *testing.T) {
-	// ANI-G ME for this test with just made up data
-	payload := "01" + "1234" + "5678" + "000000000000000000000000000000000000000000000000000000"
-	goodMessage := "0ddd520a01078001" + payload + "00000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, uint16(0x0ddd), omciMsg.TransactionID)
-	assert.Equal(t, TestRequestType, omciMsg.MessageType)
-	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
-	assert.Equal(t, uint16(40), omciMsg.Length)
-
-	msgLayer := packet.Layer(LayerTypeTestRequest)
-	assert.NotNil(t, msgLayer)
-
-	// This is a optical line test results
-	optical, ok2 := msgLayer.(*OpticalLineSupervisionTestRequest)
-	assert.True(t, ok2)
-	assert.NotNil(t, optical)
-
-	// Get the Managed Entity class ID and instance ID from the base packet
-	base := optical.MeBasePacket
-	assert.Equal(t, me.AniGClassID, base.EntityClass)
-	assert.Equal(t, uint16(0x8001), base.EntityInstance)
-
-	assert.Equal(t, uint8(1), optical.SelectTest)
-	assert.Equal(t, uint16(0x1234), optical.GeneralPurposeBuffer)
-	assert.Equal(t, uint16(0x5678), optical.VendorSpecificParameters)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestGenericTestRequestSerialize(t *testing.T) {
-	payload := "1234567891234567890123456789012345678901234567890123456789012345"
-	goodMessage := "eeee520a01000000" + payload + "00000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0xeeee,
-		MessageType:   TestRequestType,
-		// DeviceIdentifier: omci.BaselineIdent,    // Optional, defaults to Baseline
-		// Length:           0x28,					// Optional, defaults to 40 octets
-	}
-	data, derr := stringToPacket(payload)
-	assert.NoError(t, derr)
-
-	request := &TestRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.OnuGClassID,
-			EntityInstance: uint16(0),
-		},
-		Payload: data,
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestOpticalLineSupervisionTestRequestSerialize(t *testing.T) {
-	// ANI-G ME for this test with just made up data
-	payload := "01" + "1234" + "5678" + "000000000000000000000000000000000000000000000000000000"
-	goodMessage := "bbbb520a01078001" + payload + "00000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0xbbbb,
-		MessageType:   TestRequestType,
-		// DeviceIdentifier: omci.BaselineIdent,    // Optional, defaults to Baseline
-		// Length:           0x28,					// Optional, defaults to 40 octets
-	}
-	request := &OpticalLineSupervisionTestRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.AniGClassID,
-			EntityInstance: uint16(0x8001),
-		},
-		SelectTest:               uint8(1),
-		GeneralPurposeBuffer:     uint16(0x1234),
-		VendorSpecificParameters: uint16(0x5678),
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestTestResponseDecode(t *testing.T) {
-	goodMessage := "0001320A01000000000000000000000000000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, TestResponseType, omciMsg.MessageType)
-	assert.Equal(t, uint16(40), omciMsg.Length)
-
-	msgLayer := packet.Layer(LayerTypeTestResponse)
-
-	assert.NotNil(t, msgLayer)
-
-	response, ok2 := msgLayer.(*TestResponse)
-	assert.True(t, ok2)
-	assert.NotNil(t, response)
-	assert.Equal(t, me.OnuGClassID, response.EntityClass)
-	assert.Equal(t, uint16(0), response.EntityInstance)
-	assert.Equal(t, me.Success, response.Result)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestTestResponseSerialize(t *testing.T) {
-	goodMessage := "0001320A01000000000000000000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x01,
-		MessageType:   TestResponseType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &TestResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass: me.OnuGClassID,
-			// Default Instance ID is 0
-		},
-		Result: me.Success,
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestExtendedAlarmNotificationDecode(t *testing.T) {
-	//                                   1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8
-	goodMessage := "0000100b000b0104001d8000000000000000000000000000000000000000000000000000000005"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, uint16(0x0), omciMsg.TransactionID)
-	assert.Equal(t, AlarmNotificationType, omciMsg.MessageType)
-	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
-	assert.Equal(t, uint16(29), omciMsg.Length)
-
-	msgLayer := packet.Layer(LayerTypeAlarmNotification)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*AlarmNotificationMsg)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-	assert.Equal(t, me.PhysicalPathTerminationPointEthernetUniClassID, request.EntityClass)
-	assert.Equal(t, uint16(0x104), request.EntityInstance)
-	assert.Equal(t, [28]byte{
-		0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	}, request.AlarmBitmap)
-	assert.Equal(t, byte(5), request.AlarmSequenceNumber)
-
-	// Active/Clear tests
-	active, err2 := request.IsAlarmActive(0)
-	clear, err3 := request.IsAlarmClear(0)
-	assert.Nil(t, err2)
-	assert.Nil(t, err3)
-	assert.True(t, active)
-	assert.False(t, clear)
-
-	// Active/Clear for undefined alarm bits
-	active, err2 = request.IsAlarmActive(1)
-	clear, err3 = request.IsAlarmClear(1)
-	assert.NotNil(t, err2)
-	assert.NotNil(t, err3)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestExtendedAlarmNotificationSerialize(t *testing.T) {
-	//                                   1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8
-	goodMessage := "0000100b000b0104001d8000000000000000000000000000000000000000000000000000000005"
-
-	omciLayer := &OMCI{
-		TransactionID:    0,
-		MessageType:      AlarmNotificationType,
-		DeviceIdentifier: ExtendedIdent,
-		// Length parameter is optional for Extended message format serialization
-		// and if present it will be overwritten during the serialization with the
-		// actual value.
-	}
-	request := &AlarmNotificationMsg{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.PhysicalPathTerminationPointEthernetUniClassID,
-			EntityInstance: uint16(0x104),
-			Extended:       true,
-		},
-		AlarmBitmap: [28]byte{
-			0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		},
-		AlarmSequenceNumber: byte(5),
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestExtendedAttributeValueChangeDecode(t *testing.T) {
-	// Software Image Version (14 bytes) AVC
-	goodMessage := "0000110b00070000001080004d4c2d3336323600000000000000"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, uint16(0x0), omciMsg.TransactionID)
-	assert.Equal(t, AttributeValueChangeType, omciMsg.MessageType)
-	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
-	assert.Equal(t, uint16(2+14), omciMsg.Length)
-
-	msgLayer := packet.Layer(LayerTypeAttributeValueChange)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*AttributeValueChangeMsg)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-	assert.Equal(t, uint16(0x8000), request.AttributeMask)
-	assert.Equal(t, me.SoftwareImageClassID, request.EntityClass)
-	assert.Equal(t, uint16(0), request.EntityInstance)
-	assert.Equal(t, []byte{
-		0x4d, 0x4c, 0x2d, 0x33, 0x36, 0x32, 0x36,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, request.Attributes["Version"])
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestExtendedAttributeValueChangeSerialize(t *testing.T) {
-	goodMessage := "0000110b00070000001080004d4c2d3336323600000000000000"
-
-	omciLayer := &OMCI{
-		TransactionID:    0,
-		MessageType:      AttributeValueChangeType,
-		DeviceIdentifier: ExtendedIdent,
-		// Length parameter is optional for Extended message format serialization
-		// and if present it will be overwritten during the serialization with the
-		// actual value.
-	}
-	request := &AttributeValueChangeMsg{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.SoftwareImageClassID,
-			EntityInstance: uint16(0),
-			Extended:       true,
-		},
-		AttributeMask: uint16(0x8000),
-		Attributes: me.AttributeValueMap{
-			"Version": []byte{
-				0x4d, 0x4c, 0x2d, 0x33, 0x36, 0x32, 0x36,
-				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-			},
-		},
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestExtendedGenericTestResultDecode(t *testing.T) {
-	// ONU-G ME for this test with just made up data
-	payload := "1234567890123456789012345678901234567890"
-	resultLen := len(payload) / 2
-	goodMessage := "00001b0b01000000" + fmt.Sprintf("%04x", resultLen) + payload
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, uint16(0x0000), omciMsg.TransactionID)
-	assert.Equal(t, TestResultType, omciMsg.MessageType)
-	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
-	assert.Equal(t, omciMsg.Length, uint16(resultLen))
-
-	msgLayer := packet.Layer(LayerTypeTestResult)
-	assert.NotNil(t, msgLayer)
-
-	// This is a generic struct since we do not do detailed decode
-	generic, ok2 := msgLayer.(*TestResultNotification)
-	assert.True(t, ok2)
-	assert.NotNil(t, generic)
-	assert.NotNil(t, generic.MeBasePacket.Payload) // Next three all same data
-	assert.NotNil(t, generic.Payload)
-	assert.NotNil(t, generic.TestResults())
-
-	base := generic.MeBasePacket
-	assert.Equal(t, me.OnuGClassID, base.EntityClass)
-	assert.Equal(t, uint16(0), base.EntityInstance)
-
-	// For the generic Test Result, get the payload data which is all the data in
-	// the test notification past the Entity Instance value.
-	payloadData, payloadErr := stringToPacket(payload)
-	assert.NotNil(t, payloadData)
-	assert.NoError(t, payloadErr)
-	assert.Equal(t, payloadData, base.Payload)
-	assert.Equal(t, payloadData, generic.Payload)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestExtendedOpticalLineSupervisionTestResultDecode(t *testing.T) {
-	// ANI-G ME for this test with just made up data
-	payload := "010034" + "030067" + "050091" + "090034" + "0c0067" + "8901"
-	resultLen := len(payload) / 2
-	goodMessage := "00001b0b01078001" + fmt.Sprintf("%04x", resultLen) + payload
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, uint16(0x0000), omciMsg.TransactionID)
-	assert.Equal(t, TestResultType, omciMsg.MessageType)
-	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
-	assert.Equal(t, uint16(resultLen), omciMsg.Length)
-
-	msgLayer := packet.Layer(LayerTypeTestResult)
-	assert.NotNil(t, msgLayer)
-
-	// This is a optical line test results
-	optical, ok2 := msgLayer.(*OpticalLineSupervisionTestResult)
-	assert.True(t, ok2)
-	assert.NotNil(t, optical)
-
-	// Get the Managed Entity class ID and instance ID from the base packet
-	base := optical.MeBasePacket
-	assert.Equal(t, me.AniGClassID, base.EntityClass)
-	assert.Equal(t, uint16(0x8001), base.EntityInstance)
-
-	assert.Equal(t, uint8(1), optical.PowerFeedVoltageType)
-	assert.Equal(t, uint16(0x34), optical.PowerFeedVoltage)
-
-	assert.Equal(t, uint8(3), optical.ReceivedOpticalPowerType)
-	assert.Equal(t, uint16(0x67), optical.ReceivedOpticalPower)
-
-	assert.Equal(t, uint8(5), optical.MeanOpticalLaunchType)
-	assert.Equal(t, uint16(0x91), optical.MeanOpticalLaunch)
-
-	assert.Equal(t, uint8(9), optical.LaserBiasCurrentType)
-	assert.Equal(t, uint16(0x34), optical.LaserBiasCurrent)
-
-	assert.Equal(t, uint8(12), optical.TemperatureType)
-	assert.Equal(t, uint16(0x67), optical.Temperature)
-
-	assert.Equal(t, uint16(0x8901), optical.GeneralPurposeBuffer)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestExtendedGenericTestResultSerialize(t *testing.T) {
-	payload := "12345678901234567890"
-	resultLen := len(payload) / 2
-	goodMessage := "00001b0b01000000" + fmt.Sprintf("%04x", resultLen) + payload
-
-	omciLayer := &OMCI{
-		// TransactionID: 0x0c,						// Optional for notifications since TID always 0x0000
-		MessageType:      TestResultType,
-		DeviceIdentifier: ExtendedIdent,
-		// Length parameter is optional for Extended message format serialization
-		// and if present it will be overwritten during the serialization with the
-		// actual value.
-	}
-	data, derr := stringToPacket(payload)
-	assert.NoError(t, derr)
-
-	request := &TestResultNotification{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.OnuGClassID,
-			EntityInstance: uint16(0),
-			Extended:       true,
-		},
-		Payload: data,
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestExtendedOpticalLineSupervisionTestResultSerialize(t *testing.T) {
-	// ANI-G ME for this test with just made up data
-	payload := "010034" + "030067" + "050091" + "090034" + "0c0067" + "8901"
-	resultLen := len(payload) / 2
-	goodMessage := "00001b0b01078001" + fmt.Sprintf("%04x", resultLen) + payload
-
-	omciLayer := &OMCI{
-		// TransactionID: 0x0c,						// Optional for notifications since TID always 0x0000
-		MessageType:      TestResultType,
-		DeviceIdentifier: ExtendedIdent,
-		// Length parameter is optional for Extended message format serialization
-		// and if present it will be overwritten during the serialization with the
-		// actual value.
-	}
-	request := &OpticalLineSupervisionTestResult{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.AniGClassID,
-			EntityInstance: uint16(0x8001),
-			Extended:       true,
-		},
-		PowerFeedVoltageType:     uint8(1),
-		PowerFeedVoltage:         uint16(0x34),
-		ReceivedOpticalPowerType: uint8(3),
-		ReceivedOpticalPower:     uint16(0x67),
-		MeanOpticalLaunchType:    uint8(5),
-		MeanOpticalLaunch:        uint16(0x91),
-		LaserBiasCurrentType:     uint8(9),
-		LaserBiasCurrent:         uint16(0x34),
-		TemperatureType:          uint8(12),
-		Temperature:              uint16(0x67),
-		GeneralPurposeBuffer:     uint16(0x8901),
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestGetCurrentDataRequestDecode(t *testing.T) {
-	goodMessage := "035e5c0a01a90000004400000000000000000000000000000000000000000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, uint16(0x035e), omciMsg.TransactionID)
-	assert.Equal(t, GetCurrentDataRequestType, omciMsg.MessageType)
-	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
-	assert.Equal(t, uint16(40), omciMsg.Length)
-
-	msgLayer := packet.Layer(LayerTypeGetCurrentDataRequest)
-	assert.NotNil(t, msgLayer)
-
-	request, ok2 := msgLayer.(*GetCurrentDataRequest)
-	assert.True(t, ok2)
-	assert.NotNil(t, request)
-	assert.Equal(t, me.EthernetFrameExtendedPm64BitClassID, request.EntityClass)
-	assert.Equal(t, uint16(0), request.EntityInstance)
-	assert.Equal(t, uint16(0x0044), request.AttributeMask)
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestGetCurrentDataRequestSerialize(t *testing.T) {
-	goodMessage := "035e5c0a01a90000004400000000000000000000000000000000000000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x035e,
-		MessageType:   GetCurrentDataRequestType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &GetCurrentDataRequest{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.EthernetFrameExtendedPm64BitClassID,
-			EntityInstance: uint16(0),
-		},
-		AttributeMask: uint16(0x0044),
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-func TestGetCurrentDataResponseDecode(t *testing.T) {
-	goodMessage := "035e3c0a01a90000000044123456781234dbcb432187654321dac1000000000000000000000000000028"
-	data, err := stringToPacket(goodMessage)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, uint16(0x035e), omciMsg.TransactionID)
-	assert.Equal(t, GetCurrentDataResponseType, omciMsg.MessageType)
-	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
-	assert.Equal(t, uint16(40), omciMsg.Length)
-
-	msgLayer := packet.Layer(LayerTypeGetCurrentDataResponse)
-	assert.NotNil(t, msgLayer)
-
-	response, ok2 := msgLayer.(*GetCurrentDataResponse)
-	assert.True(t, ok2)
-	assert.NotNil(t, response)
-	assert.Equal(t, me.EthernetFrameExtendedPm64BitClassID, response.EntityClass)
-	assert.Equal(t, uint16(0), response.EntityInstance)
-	assert.Equal(t, me.Success, response.Result)
-	assert.Equal(t, uint16(0x0044), response.AttributeMask)
-	assert.Equal(t, uint64(0x123456781234dbcb), response.Attributes["OversizeFrames"])
-	assert.Equal(t, uint64(0x432187654321dac1), response.Attributes["Frames256To511Octets"])
-
-	// Verify string output for message
-	packetString := packet.String()
-	assert.NotZero(t, len(packetString))
-}
-
-func TestGetCurrentDataResponseSerialize(t *testing.T) {
-	goodMessage := "035e3c0a01a90000000044123456781234dbcb432187654321dac10000000000000000000000000000000028"
-
-	omciLayer := &OMCI{
-		TransactionID: 0x035e,
-		MessageType:   GetCurrentDataResponseType,
-		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
-		// Length:           0x28,						// Optional, defaults to 40 octets
-	}
-	request := &GetCurrentDataResponse{
-		MeBasePacket: MeBasePacket{
-			EntityClass:    me.EthernetFrameExtendedPm64BitClassID,
-			EntityInstance: uint16(0),
-		},
-		Result:        0,
-		AttributeMask: uint16(0x0044),
-		Attributes: me.AttributeValueMap{
-			"OversizeFrames":       uint64(0x123456781234dbcb),
-			"Frames256To511Octets": uint64(0x432187654321dac1),
-			// BroadcastFrames can be supplied but will not be encoded since not in attribute mask.
-			"BroadcastFrames": uint64(0x0123456789abcdef)},
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
-}
-
-// TODO: Also remember to add extended message tests to the meframe_test.go
-//       unit tests as more message types are supported
diff --git a/mibreset.go b/mibreset.go
new file mode 100644
index 0000000..564f85d
--- /dev/null
+++ b/mibreset.go
@@ -0,0 +1,231 @@
+/*
+ * 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"
+	"github.com/google/gopacket"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+type MibResetRequest struct {
+	MeBasePacket
+}
+
+func (omci *MibResetRequest) String() string {
+	return fmt.Sprintf("%v", omci.MeBasePacket.String())
+}
+
+// LayerType returns LayerTypeMibResetRequest
+func (omci *MibResetRequest) LayerType() gopacket.LayerType {
+	return LayerTypeMibResetRequest
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *MibResetRequest) CanDecode() gopacket.LayerClass {
+	return LayerTypeMibResetRequest
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *MibResetRequest) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6
+	} else {
+		hdrSize = 4
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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)
+}
+
+func decodeMibResetRequestExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &MibResetRequest{}
+	omci.MsgLayerType = LayerTypeMibResetRequest
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an MIB Reset Request message
+func (omci *MibResetRequest) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
+	// MibReset Entity Class are always ONU DATA (2) and Entity Instance of 0
+	if omci.EntityClass != me.OnuDataClassID {
+		return me.NewProcessingError("invalid Entity Class for MIB Reset request")
+	}
+	if omci.EntityInstance != 0 {
+		return me.NewUnknownInstanceError("invalid Entity Instance for MIB Reset request")
+	}
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	// Add length if extended ident
+	if omci.Extended {
+		bytes, err := b.AppendBytes(2)
+		if err != nil {
+			return err
+		}
+		binary.BigEndian.PutUint16(bytes, 0)
+	}
+	return nil
+}
+
+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)
+}
+
+// LayerType returns LayerTypeMibResetResponse
+func (omci *MibResetResponse) LayerType() gopacket.LayerType {
+	return LayerTypeMibResetResponse
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *MibResetResponse) CanDecode() gopacket.LayerClass {
+	return LayerTypeMibResetResponse
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *MibResetResponse) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6 + 1
+	} else {
+		hdrSize = 4 + 1
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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")
+	}
+	offset := hdrSize - 1
+	omci.Result = me.Results(data[offset])
+	if omci.Result > me.DeviceBusy {
+		msg := fmt.Sprintf("invalid results code: %v, must be 0..6", 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)
+}
+
+func decodeMibResetResponseExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &MibResetResponse{}
+	omci.MsgLayerType = LayerTypeMibResetResponse
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an MIB Reset Response message
+func (omci *MibResetResponse) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	bytes, err := b.AppendBytes(offset + 1)
+	if err != nil {
+		return err
+	}
+	// Add length if extended ident
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, 1)
+	}
+	bytes[offset] = byte(omci.Result)
+	return nil
+}
diff --git a/mibreset_test.go b/mibreset_test.go
new file mode 100644
index 0000000..cd50f39
--- /dev/null
+++ b/mibreset_test.go
@@ -0,0 +1,371 @@
+/*
+ * 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_test
+
+import (
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/stretchr/testify/assert"
+	"strings"
+	"testing"
+)
+
+func TestMibResetRequestDecode(t *testing.T) {
+	goodMessage := "01094f0a00020000000000000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeMibResetRequest, omciMsg.NextLayerType())
+	assert.Equal(t, MibResetRequestType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeMibResetRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*MibResetRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeMibResetRequest, request.LayerType())
+	assert.Equal(t, LayerTypeMibResetRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, me.OnuDataClassID, request.EntityClass)
+	assert.Equal(t, uint16(0), request.EntityInstance)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestMibResetRequestSerialize(t *testing.T) {
+	goodMessage := "01094f0a00020000000000000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x0109,
+		MessageType:   MibResetRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &MibResetRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass: me.OnuDataClassID,
+			// Default Instance ID is 0
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestMibResetRequestZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   MibResetRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &MibResetRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass: me.OnuDataClassID,
+			// Default Instance ID is 0
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestMibResetResponseDecode(t *testing.T) {
+	goodMessage := "00012F0A00020000000000000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeMibResetResponse, omciMsg.NextLayerType())
+	assert.Equal(t, MibResetResponseType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeMibResetResponse)
+
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*MibResetResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeMibResetResponse, response.LayerType())
+	assert.Equal(t, LayerTypeMibResetResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestMibResetResponseSerialize(t *testing.T) {
+	goodMessage := "00012F0A00020000000000000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x01,
+		MessageType:   MibResetResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &MibResetResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass: me.OnuDataClassID,
+			// Default Instance ID is 0
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestMibResetResponseZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   MibResetResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &MibResetResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass: me.OnuDataClassID,
+			// Default Instance ID is 0
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestExtendedMibResetRequestDecode(t *testing.T) {
+	goodMessage := "01094f0b000200000000"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeMibResetRequest, omciMsg.NextLayerType())
+	assert.Equal(t, MibResetRequestType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(0), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeMibResetRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*MibResetRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeMibResetRequest, request.LayerType())
+	assert.Equal(t, LayerTypeMibResetRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, me.OnuDataClassID, request.EntityClass)
+	assert.Equal(t, uint16(0), request.EntityInstance)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedMibResetRequestSerialize(t *testing.T) {
+	goodMessage := "01094f0b000200000000"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0109,
+		MessageType:      MibResetRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &MibResetRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass: me.OnuDataClassID,
+			Extended:    true,
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestExtendedMibResetResponseDecode(t *testing.T) {
+	goodMessage := "00012F0B00020000000106"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeMibResetResponse, omciMsg.NextLayerType())
+	assert.Equal(t, MibResetResponseType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(1), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeMibResetResponse)
+
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*MibResetResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, me.DeviceBusy, response.Result)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedMibResetResponseSerialize(t *testing.T) {
+	goodMessage := "00012F0B00020000000106"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x01,
+		MessageType:      MibResetResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &MibResetResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass: me.OnuDataClassID,
+			Extended:    true,
+		},
+		Result: me.DeviceBusy,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+// MibResetRequestTest tests decode/encode of a MIB Reset Request
+func TestMibResetRequestMessage(t *testing.T) {
+	mibResetRequest := "00014F0A000200000000000000000000" +
+		"00000000000000000000000000000000" +
+		"000000000000000000000028"
+
+	data, err := stringToPacket(mibResetRequest)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, packet)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, uint16(1), omciMsg.TransactionID)
+	assert.Equal(t, MibResetRequestType, omciMsg.MessageType)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeMibResetRequest)
+	assert.NotNil(t, msgLayer)
+
+	omciMsg2, ok2 := msgLayer.(*MibResetRequest)
+	assert.True(t, ok2)
+	assert.Equal(t, me.OnuDataClassID, omciMsg2.EntityClass)
+	assert.Equal(t, uint16(0), omciMsg2.EntityInstance)
+
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err = gopacket.SerializeLayers(buffer, options, omciMsg, omciMsg2)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(mibResetRequest), reconstituted)
+}
diff --git a/mibupload.go b/mibupload.go
new file mode 100644
index 0000000..dd893d4
--- /dev/null
+++ b/mibupload.go
@@ -0,0 +1,550 @@
+/*
+ * 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"
+	"github.com/google/gopacket"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+type MibUploadRequest struct {
+	MeBasePacket
+}
+
+func (omci *MibUploadRequest) String() string {
+	return fmt.Sprintf("%v", omci.MeBasePacket.String())
+}
+
+// LayerType returns LayerTypeMibUploadRequest
+func (omci *MibUploadRequest) LayerType() gopacket.LayerType {
+	return LayerTypeMibUploadRequest
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *MibUploadRequest) CanDecode() gopacket.LayerClass {
+	return LayerTypeMibUploadRequest
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *MibUploadRequest) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6
+	} else {
+		hdrSize = 4
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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)
+}
+
+func decodeMibUploadRequestExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &MibUploadRequest{}
+	omci.MsgLayerType = LayerTypeMibUploadRequest
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an MIB Upload Request message
+func (omci *MibUploadRequest) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	// Add length if extended ident
+	if omci.Extended {
+		bytes, err := b.AppendBytes(2)
+		if err != nil {
+			return err
+		}
+		binary.BigEndian.PutUint16(bytes, 0)
+	}
+	return nil
+}
+
+type MibUploadResponse struct {
+	MeBasePacket
+	NumberOfCommands uint16
+}
+
+func (omci *MibUploadResponse) String() string {
+	return fmt.Sprintf("%v, NumberOfCommands: %#v",
+		omci.MeBasePacket.String(), omci.NumberOfCommands)
+}
+
+// LayerType returns LayerTypeMibUploadResponse
+func (omci *MibUploadResponse) LayerType() gopacket.LayerType {
+	return LayerTypeMibUploadResponse
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *MibUploadResponse) CanDecode() gopacket.LayerClass {
+	return LayerTypeMibUploadResponse
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *MibUploadResponse) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6 + 2
+	} else {
+		hdrSize = 4 + 2
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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)
+	}
+	offset := hdrSize - 2
+	omci.NumberOfCommands = binary.BigEndian.Uint16(data[offset:])
+	return nil
+}
+
+func decodeMibUploadResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &MibUploadResponse{}
+	omci.MsgLayerType = LayerTypeMibUploadResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+func decodeMibUploadResponseExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &MibUploadResponse{}
+	omci.MsgLayerType = LayerTypeMibUploadResponse
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an MIB Upload Response message
+func (omci *MibUploadResponse) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header
+	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")
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	bytes, err := b.AppendBytes(offset + 2)
+	if err != nil {
+		return err
+	}
+	// Add length if extended ident
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, 2)
+	}
+	binary.BigEndian.PutUint16(bytes[offset:], 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)
+}
+
+// LayerType returns LayerTypeMibUploadNextRequest
+func (omci *MibUploadNextRequest) LayerType() gopacket.LayerType {
+	return LayerTypeMibUploadNextRequest
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *MibUploadNextRequest) CanDecode() gopacket.LayerClass {
+	return LayerTypeMibUploadNextRequest
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *MibUploadNextRequest) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6 + 2
+	} else {
+		hdrSize = 4 + 2
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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)
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	omci.CommandSequenceNumber = binary.BigEndian.Uint16(data[4+offset:])
+	return nil
+}
+
+func decodeMibUploadNextRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &MibUploadNextRequest{}
+	omci.MsgLayerType = LayerTypeMibUploadNextRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+func decodeMibUploadNextRequestExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &MibUploadNextRequest{}
+	omci.MsgLayerType = LayerTypeMibUploadNextRequest
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an MIB Upload Next Request message
+func (omci *MibUploadNextRequest) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	bytes, err := b.AppendBytes(2 + offset)
+	if err != nil {
+		return err
+	}
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, 2)
+	}
+	binary.BigEndian.PutUint16(bytes[offset:], omci.CommandSequenceNumber)
+	return nil
+}
+
+type IMibUploadNextResponse interface {
+	GetMeBasePacket() *MeBasePacket
+	GetMeCount() int
+	GetManagedEntity(int) *me.ManagedEntity
+	AddManagedEntity(*me.ManagedEntity) error
+}
+
+type MibUploadNextResponse struct {
+	MeBasePacket
+	ReportedME    me.ManagedEntity
+	AdditionalMEs []me.ManagedEntity // Valid only for extended message set version
+}
+
+type MibUploadNextManageEntity struct {
+	AttrSize   uint16 // Size of ME instance attribute values included
+	ReportedME me.ManagedEntity
+}
+
+func (omci *MibUploadNextResponse) String() string {
+	return fmt.Sprintf("%v, ReportedME: [%v]",
+		omci.MeBasePacket.String(), omci.ReportedME.String())
+}
+
+// LayerType returns LayerTypeMibUploadNextResponse
+func (omci *MibUploadNextResponse) LayerType() gopacket.LayerType {
+	return LayerTypeMibUploadNextResponse
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *MibUploadNextResponse) CanDecode() gopacket.LayerClass {
+	return LayerTypeMibUploadNextResponse
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *MibUploadNextResponse) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6
+	} else {
+		hdrSize = 4
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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.
+	var offset int
+	var attrLen int
+	if omci.Extended {
+		offset = 2 + 2 // Message Contents length (2) + first ME attribute values len (2)
+		attrLen = int(binary.BigEndian.Uint16(data[6:]))
+
+		if len(data[4+offset:]) < 6+attrLen {
+			p.SetTruncated()
+			return errors.New("frame too small: MIB Upload Response Managed Entity attribute truncated")
+		}
+	}
+	err = omci.ReportedME.DecodeFromBytes(data[4+offset:], p, byte(MibUploadNextResponseType))
+	if err != nil || !omci.Extended {
+		return err
+	}
+	// Handle extended message set decode here for additional attributes
+	remaining := len(data) - (6 + 8 + attrLen)
+	if remaining > 0 {
+		offset = 6 + 8 + attrLen
+		omci.AdditionalMEs = make([]me.ManagedEntity, 0)
+		for remaining > 0 {
+			if len(data[offset:]) < 8 {
+				p.SetTruncated()
+				// TODO: Review all "frame to small" and add an extra hint for developers
+				return errors.New("frame too small: MIB Upload Response Managed Entity header truncated")
+			}
+			additional := me.ManagedEntity{}
+			attrLen = int(binary.BigEndian.Uint16(data[offset:]))
+
+			if len(data[offset:]) < 8+attrLen {
+				p.SetTruncated()
+				return errors.New("frame too small: MIB Upload Response Managed Entity attribute truncated")
+			}
+			err = additional.DecodeFromBytes(data[offset+2:], p, byte(MibUploadNextResponseType))
+			if err != nil {
+				return err
+			}
+			omci.AdditionalMEs = append(omci.AdditionalMEs, additional)
+			remaining -= 8 + attrLen
+			offset += 8 + attrLen
+		}
+	}
+	return nil
+}
+
+func decodeMibUploadNextResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &MibUploadNextResponse{}
+	omci.MsgLayerType = LayerTypeMibUploadNextResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+func decodeMibUploadNextResponseExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &MibUploadNextResponse{}
+	omci.MsgLayerType = LayerTypeMibUploadNextResponse
+	omci.Extended = true
+	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
+	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")
+	}
+	bytesAvailable := MaxBaselineLength - 8 - 8
+
+	if omci.Extended {
+		bytesAvailable = MaxExtendedLength - 10 - 4
+	}
+	attributeBuffer := gopacket.NewSerializeBuffer()
+	attrErr := omci.ReportedME.SerializeTo(attributeBuffer, byte(MibUploadNextResponseType), bytesAvailable, opts)
+	if attrErr != nil {
+		return attrErr
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2 + 2 // Message Contents length (2) + first ME attribute values len (2)
+	}
+	meLength := len(attributeBuffer.Bytes())
+	buf, attrErr := b.AppendBytes(meLength + offset)
+	if attrErr != nil {
+		return attrErr
+	}
+	if omci.Extended {
+		binary.BigEndian.PutUint16(buf, uint16(meLength+2))
+		binary.BigEndian.PutUint16(buf[2:], uint16(meLength-6))
+	}
+	copy(buf[offset:], attributeBuffer.Bytes())
+
+	if omci.Extended && omci.AdditionalMEs != nil {
+		// Handle additional Managed Entities here for the Extended Message set
+		bytesAvailable -= 4 + meLength
+		length := meLength + 2
+
+		for index, entry := range omci.AdditionalMEs {
+			if bytesAvailable <= 8 {
+				msg := fmt.Sprintf("not enough space to fit all requested Managed Entities, entry: %v", index)
+				attrErr = me.NewMessageTruncatedError(msg)
+				if attrErr != nil {
+					return attrErr
+				}
+			}
+			attributeBuffer = gopacket.NewSerializeBuffer()
+			attrErr = entry.SerializeTo(attributeBuffer, byte(MibUploadNextResponseType), bytesAvailable, opts)
+			if attrErr != nil {
+				return attrErr
+			}
+			meLength = len(attributeBuffer.Bytes())
+			buf, attrErr = b.AppendBytes(2 + meLength)
+			if attrErr != nil {
+				return attrErr
+			}
+			binary.BigEndian.PutUint16(buf, uint16(meLength-6))
+			copy(buf[2:], attributeBuffer.Bytes())
+			length += 2 + meLength
+			bytesAvailable -= 2 + meLength
+		}
+		msgBuffer := b.Bytes()
+		binary.BigEndian.PutUint16(msgBuffer[4:], uint16(length))
+	}
+	return nil
+}
diff --git a/mibupload_test.go b/mibupload_test.go
new file mode 100644
index 0000000..8fcc983
--- /dev/null
+++ b/mibupload_test.go
@@ -0,0 +1,1749 @@
+/*
+ * 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_test
+
+import (
+	"fmt"
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/stretchr/testify/assert"
+	"strings"
+	"testing"
+)
+
+func TestMibUploadRequestDecode(t *testing.T) {
+	goodMessage := "03604d0a00020000000000000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeMibUploadRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0360), omciMsg.TransactionID)
+	assert.Equal(t, MibUploadRequestType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+	msgLayer := packet.Layer(LayerTypeMibUploadRequest)
+
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*MibUploadRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeMibUploadRequest, request.LayerType())
+	assert.Equal(t, LayerTypeMibUploadRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestMibUploadRequestDecodeExtended(t *testing.T) {
+	goodMessage := "03604d0b000200000000"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeMibUploadRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0360), omciMsg.TransactionID)
+	assert.Equal(t, MibUploadRequestType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(0), omciMsg.Length)
+	msgLayer := packet.Layer(LayerTypeMibUploadRequest)
+
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*MibUploadRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeMibUploadRequest, request.LayerType())
+	assert.Equal(t, LayerTypeMibUploadRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestMibUploadRequestSerialize(t *testing.T) {
+	goodMessage := "03604d0a00020000000000000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x0360,
+		MessageType:   MibUploadRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &MibUploadRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestMibUploadRequestZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   MibUploadRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &MibUploadRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestMibUploadRequestSerializeExtended(t *testing.T) {
+	goodMessage := "03604d0b000200000000"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0360,
+		MessageType:      MibUploadRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &MibUploadRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+			Extended:       true,
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestMibUploadResponseDecode(t *testing.T) {
+	goodMessage := "03602d0a00020000011200000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeMibUploadResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0360), omciMsg.TransactionID)
+	assert.Equal(t, MibUploadResponseType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeMibUploadResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*MibUploadResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeMibUploadResponse, response.LayerType())
+	assert.Equal(t, LayerTypeMibUploadResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, response.NumberOfCommands, uint16(0x112))
+}
+
+func TestMibUploadResponseDecodeExtended(t *testing.T) {
+	goodMessage := "03602d0b0002000000020112"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeMibUploadResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0360), omciMsg.TransactionID)
+	assert.Equal(t, MibUploadResponseType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(2), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeMibUploadResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*MibUploadResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeMibUploadResponse, response.LayerType())
+	assert.Equal(t, LayerTypeMibUploadResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, response.NumberOfCommands, uint16(0x112))
+}
+
+func TestMibUploadResponseSerialize(t *testing.T) {
+	goodMessage := "03602d0a00020000011200000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x0360,
+		MessageType:   MibUploadResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &MibUploadResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+		},
+		NumberOfCommands: uint16(0x112),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestMibUploadResponseZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   MibUploadResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &MibUploadResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+		},
+		NumberOfCommands: uint16(0x112),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestMibUploadResponseSerializeExtended(t *testing.T) {
+	goodMessage := "03602d0b0002000000020112"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0360,
+		MessageType:      MibUploadResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &MibUploadResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+			Extended:       true,
+		},
+		NumberOfCommands: uint16(0x112),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestMibUploadNextRequestDecode(t *testing.T) {
+	goodMessage := "02864e0a00020000003a00000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeMibUploadNextRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0286), omciMsg.TransactionID)
+	assert.Equal(t, MibUploadNextRequestType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeMibUploadNextRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*MibUploadNextRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeMibUploadNextRequest, request.LayerType())
+	assert.Equal(t, LayerTypeMibUploadNextRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, uint16(0x3a), request.CommandSequenceNumber)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestMibUploadNextRequestDecodeExtended(t *testing.T) {
+	goodMessage := "02864e0b000200000002003a"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeMibUploadNextRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0286), omciMsg.TransactionID)
+	assert.Equal(t, MibUploadNextRequestType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(2), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeMibUploadNextRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*MibUploadNextRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeMibUploadNextRequest, request.LayerType())
+	assert.Equal(t, LayerTypeMibUploadNextRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, uint16(0x3a), request.CommandSequenceNumber)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestMibUploadNextRequestSerialize(t *testing.T) {
+	goodMessage := "02864e0a00020000003a00000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x0286,
+		MessageType:   MibUploadNextRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &MibUploadNextRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+		},
+		CommandSequenceNumber: uint16(0x3a),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestMibUploadNextRequestZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   MibUploadNextRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &MibUploadNextRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+		},
+		CommandSequenceNumber: uint16(0x3a),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestMibUploadNextRequestSerializeExtended(t *testing.T) {
+	goodMessage := "02864e0b000200000002003a"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0286,
+		MessageType:      MibUploadNextRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &MibUploadNextRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+			Extended:       true,
+		},
+		CommandSequenceNumber: uint16(0x3a),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestMibUploadNextResponseDecode(t *testing.T) {
+	goodMessage := "02862e0a0002000001150000fff0000000000000000000010100000000010000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeMibUploadNextResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0286), omciMsg.TransactionID)
+	assert.Equal(t, MibUploadNextResponseType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeMibUploadNextResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*MibUploadNextResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeMibUploadNextResponse, response.LayerType())
+	assert.Equal(t, LayerTypeMibUploadNextResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, me.PriorityQueueClassID, response.ReportedME.GetClassID())
+	assert.Equal(t, uint16(0), response.ReportedME.GetEntityID())
+
+	attributes := me.AttributeValueMap{
+		"QueueConfigurationOption":                            byte(0),
+		"MaximumQueueSize":                                    uint16(0),
+		"AllocatedQueueSize":                                  uint16(0),
+		"DiscardBlockCounterResetInterval":                    uint16(0),
+		"ThresholdValueForDiscardedBlocksDueToBufferOverflow": uint16(0),
+		"RelatedPort":                                         uint32(16842752),
+		"TrafficSchedulerPointer":                             uint16(0),
+		"Weight":                                              byte(1),
+		"BackPressureOperation":                               uint16(0),
+		"BackPressureTime":                                    uint32(0),
+		"BackPressureOccurQueueThreshold":                     uint16(0),
+		"BackPressureClearQueueThreshold":                     uint16(0),
+	}
+	for name, value := range attributes {
+		pktValue, err := response.ReportedME.GetAttribute(name)
+		assert.Nil(t, err)
+		assert.Equal(t, pktValue, value)
+	}
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestMibUploadNextResponseDecodeExtendedOneMe(t *testing.T) {
+	firstMe := "001801150000ffe001123443215678876501010000FFBB011234000000006789"
+	goodMessage := "02862e0b000200000020" + firstMe
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeMibUploadNextResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0286), omciMsg.TransactionID)
+	assert.Equal(t, MibUploadNextResponseType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(2+6+24), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeMibUploadNextResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*MibUploadNextResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeMibUploadNextResponse, response.LayerType())
+	assert.Equal(t, LayerTypeMibUploadNextResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, me.PriorityQueueClassID, response.ReportedME.GetClassID())
+	assert.Equal(t, uint16(0), response.ReportedME.GetEntityID())
+
+	attributes := me.AttributeValueMap{
+		"QueueConfigurationOption":                            byte(1),
+		"MaximumQueueSize":                                    uint16(0x1234),
+		"AllocatedQueueSize":                                  uint16(0x4321),
+		"DiscardBlockCounterResetInterval":                    uint16(0x5678),
+		"ThresholdValueForDiscardedBlocksDueToBufferOverflow": uint16(0x8765),
+		"RelatedPort":                                         uint32(16842752),
+		"TrafficSchedulerPointer":                             uint16(0xFFBB),
+		"Weight":                                              byte(1),
+		"BackPressureOperation":                               uint16(0x1234),
+		"BackPressureTime":                                    uint32(0),
+		"BackPressureOccurQueueThreshold":                     uint16(0x6789),
+	}
+	// 01 1234 4321 5678 8765 01010000 FFBB 01 1234 00000000 6789
+	// 01123443215678876501010000FFBB011234000000006789
+	//  1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4
+	for name, value := range attributes {
+		pktValue, err := response.ReportedME.GetAttribute(name)
+		assert.Nil(t, err)
+		assert.Equal(t, value, pktValue)
+	}
+	// Only the first ME
+	assert.Nil(t, response.AdditionalMEs)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestMibUploadNextResponseDecodeExtendedThreeMe(t *testing.T) {
+	first := "001801150000ffe001123443215678876501010000FFBB011234000000006789"
+	second := "001801150001ffe001123443215678876501010000FFBB011234000000006789"
+	third := "001801150002ffe001123443215678876501010000FFBB011234000000006789"
+	goodMessage := "02862e0b000200000060" + first + second + third
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	// TODO: Implement and test
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeMibUploadNextResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0286), omciMsg.TransactionID)
+	assert.Equal(t, MibUploadNextResponseType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(3*(8+24)), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeMibUploadNextResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*MibUploadNextResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeMibUploadNextResponse, response.LayerType())
+	assert.Equal(t, LayerTypeMibUploadNextResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, me.PriorityQueueClassID, response.ReportedME.GetClassID())
+	assert.Equal(t, uint16(0), response.ReportedME.GetEntityID())
+
+	attributes := me.AttributeValueMap{
+		"QueueConfigurationOption":                            byte(1),
+		"MaximumQueueSize":                                    uint16(0x1234),
+		"AllocatedQueueSize":                                  uint16(0x4321),
+		"DiscardBlockCounterResetInterval":                    uint16(0x5678),
+		"ThresholdValueForDiscardedBlocksDueToBufferOverflow": uint16(0x8765),
+		"RelatedPort":                                         uint32(16842752),
+		"TrafficSchedulerPointer":                             uint16(0xFFBB),
+		"Weight":                                              byte(1),
+		"BackPressureOperation":                               uint16(0x1234),
+		"BackPressureTime":                                    uint32(0),
+		"BackPressureOccurQueueThreshold":                     uint16(0x6789),
+	}
+	// 01 1234 4321 5678 8765 01010000 FFBB 01 1234 00000000 6789
+	// 01123443215678876501010000FFBB011234000000006789
+	//  1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4
+	for name, value := range attributes {
+		pktValue, err := response.ReportedME.GetAttribute(name)
+		assert.Nil(t, err)
+		assert.Equal(t, value, pktValue)
+	}
+	// Other two are the same, just different managed entity IDs
+
+	assert.Equal(t, 2, len(response.AdditionalMEs))
+	assert.Equal(t, me.PriorityQueueClassID, response.AdditionalMEs[0].GetClassID())
+	assert.Equal(t, uint16(1), response.AdditionalMEs[0].GetEntityID())
+	for name, value := range attributes {
+		pktValue, err := response.AdditionalMEs[0].GetAttribute(name)
+		assert.Nil(t, err)
+		assert.Equal(t, value, pktValue)
+	}
+	assert.Equal(t, me.PriorityQueueClassID, response.AdditionalMEs[1].GetClassID())
+	assert.Equal(t, uint16(2), response.AdditionalMEs[1].GetEntityID())
+	for name, value := range attributes {
+		pktValue, err := response.AdditionalMEs[1].GetAttribute(name)
+		assert.Nil(t, err)
+		assert.Equal(t, value, pktValue)
+	}
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestMibUploadNextResponseDecodeExtendedMaxLength(t *testing.T) {
+	// Max payload after header length field and not including MIC is 1966 octets
+	maxPayloadLen := MaxExtendedLength - 10 - 4
+
+	// Payload is AttrLen (2) + ME Hdr (6) + attributes which is 30 octets
+	// below. That allows 65 'common' payloads with a remainder of 16 octets
+	// to fill with another ME
+	commonPayloadFmt := "00160115%04xffc001123443215678876501010000FFBB01123487654321"
+	lastPayload := "00080115000078001234432156788765"
+	msgHeader := fmt.Sprintf("02862e0b00020000%04x", maxPayloadLen)
+	numCommon := 65
+
+	goodMessage := msgHeader + fmt.Sprintf(commonPayloadFmt, 0)
+	for instance := 1; instance < numCommon; instance++ {
+		goodMessage += fmt.Sprintf(commonPayloadFmt, instance)
+	}
+	goodMessage += lastPayload
+
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+	assert.Equal(t, MaxExtendedLength-4, len(data))
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeMibUploadNextResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0286), omciMsg.TransactionID)
+	assert.Equal(t, MibUploadNextResponseType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(maxPayloadLen), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeMibUploadNextResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*MibUploadNextResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeMibUploadNextResponse, response.LayerType())
+	assert.Equal(t, LayerTypeMibUploadNextResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, me.PriorityQueueClassID, response.ReportedME.GetClassID())
+	assert.Equal(t, uint16(0), response.ReportedME.GetEntityID())
+
+	attributes := me.AttributeValueMap{
+		"QueueConfigurationOption":                            byte(1),
+		"MaximumQueueSize":                                    uint16(0x1234),
+		"AllocatedQueueSize":                                  uint16(0x4321),
+		"DiscardBlockCounterResetInterval":                    uint16(0x5678),
+		"ThresholdValueForDiscardedBlocksDueToBufferOverflow": uint16(0x8765),
+		"RelatedPort":                                         uint32(16842752),
+		"TrafficSchedulerPointer":                             uint16(0xFFBB),
+		"Weight":                                              byte(1),
+		"BackPressureOperation":                               uint16(0x1234),
+		"BackPressureTime":                                    uint32(0x87654321),
+	}
+	lastPayloadAttributes := me.AttributeValueMap{
+		"MaximumQueueSize":                                    uint16(0x1234),
+		"AllocatedQueueSize":                                  uint16(0x4321),
+		"DiscardBlockCounterResetInterval":                    uint16(0x5678),
+		"ThresholdValueForDiscardedBlocksDueToBufferOverflow": uint16(0x8765),
+	}
+	// Check first ME that is stored in same location as in baseline message
+	for name, value := range attributes {
+		pktValue, err := response.ReportedME.GetAttribute(name)
+		assert.Nil(t, err)
+		assert.Equal(t, value, pktValue)
+	}
+	// Check remainder of the package = (numCommon - 1) + trailing me
+	assert.Equal(t, numCommon, len(response.AdditionalMEs))
+	for index, additional := range response.AdditionalMEs {
+		if index == numCommon-1 {
+			break
+		}
+		assert.Equal(t, me.PriorityQueueClassID, additional.GetClassID())
+		assert.Equal(t, uint16(index+1), additional.GetEntityID())
+		for name, value := range attributes {
+			pktValue, err := additional.GetAttribute(name)
+			assert.Nil(t, err)
+			assert.Equal(t, value, pktValue)
+		}
+	}
+	// And check the last one
+	assert.Equal(t, me.PriorityQueueClassID, response.AdditionalMEs[numCommon-1].GetClassID())
+	assert.Equal(t, uint16(0), response.AdditionalMEs[numCommon-1].GetEntityID())
+	for name, value := range lastPayloadAttributes {
+		pktValue, err := response.AdditionalMEs[numCommon-1].GetAttribute(name)
+		assert.Nil(t, err)
+		assert.Equal(t, value, pktValue)
+	}
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestMibUploadNextResponseSerialize(t *testing.T) {
+	goodMessage := "02862e0a0002000001150000fff0000000000000000000010100000000010002000000030004000500000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x0286,
+		MessageType:   MibUploadNextResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	paramData := me.ParamData{
+		EntityID: uint16(0),
+		Attributes: me.AttributeValueMap{
+			"QueueConfigurationOption":                            byte(0),
+			"MaximumQueueSize":                                    uint16(0),
+			"AllocatedQueueSize":                                  uint16(0),
+			"DiscardBlockCounterResetInterval":                    uint16(0),
+			"ThresholdValueForDiscardedBlocksDueToBufferOverflow": uint16(0),
+			"RelatedPort":                                         uint32(16842752),
+			"TrafficSchedulerPointer":                             uint16(0),
+			"Weight":                                              byte(1),
+			"BackPressureOperation":                               uint16(2),
+			"BackPressureTime":                                    uint32(3),
+			"BackPressureOccurQueueThreshold":                     uint16(4),
+			"BackPressureClearQueueThreshold":                     uint16(5),
+		},
+	}
+	reportedME, err := me.NewPriorityQueue(paramData)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	request := &MibUploadNextResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+		},
+		ReportedME: *reportedME,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	omciErr := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, omciErr)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestMibUploadNextResponseZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   MibUploadNextResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	paramData := me.ParamData{
+		EntityID: uint16(0),
+		Attributes: me.AttributeValueMap{
+			"QueueConfigurationOption":                            byte(0),
+			"MaximumQueueSize":                                    uint16(0),
+			"AllocatedQueueSize":                                  uint16(0),
+			"DiscardBlockCounterResetInterval":                    uint16(0),
+			"ThresholdValueForDiscardedBlocksDueToBufferOverflow": uint16(0),
+			"RelatedPort":                                         uint32(16842752),
+			"TrafficSchedulerPointer":                             uint16(0),
+			"Weight":                                              byte(1),
+			"BackPressureOperation":                               uint16(2),
+			"BackPressureTime":                                    uint32(3),
+			"BackPressureOccurQueueThreshold":                     uint16(4),
+			"BackPressureClearQueueThreshold":                     uint16(5),
+		},
+	}
+	reportedME, err := me.NewPriorityQueue(paramData)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	request := &MibUploadNextResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+		},
+		ReportedME: *reportedME,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	omciErr := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, omciErr)
+}
+
+func TestMibUploadNextResponseSerializeExtendedOneMe(t *testing.T) {
+	firstMe := "001801150000ffe001123443215678876501010000FFBB011234000000006789"
+	goodMessage := "02862e0b000200000020" + firstMe
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0286,
+		MessageType:      MibUploadNextResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	paramData := me.ParamData{
+		EntityID: uint16(0),
+		Attributes: me.AttributeValueMap{
+			"QueueConfigurationOption":                            byte(1),
+			"MaximumQueueSize":                                    uint16(0x1234),
+			"AllocatedQueueSize":                                  uint16(0x4321),
+			"DiscardBlockCounterResetInterval":                    uint16(0x5678),
+			"ThresholdValueForDiscardedBlocksDueToBufferOverflow": uint16(0x8765),
+			"RelatedPort":                                         uint32(16842752),
+			"TrafficSchedulerPointer":                             uint16(0xFFBB),
+			"Weight":                                              byte(1),
+			"BackPressureOperation":                               uint16(0x1234),
+			"BackPressureTime":                                    uint32(0),
+			"BackPressureOccurQueueThreshold":                     uint16(0x6789),
+		},
+	}
+	reportedME, err := me.NewPriorityQueue(paramData)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+
+	request := &MibUploadNextResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+			Extended:       true,
+		},
+		ReportedME: *reportedME,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	omciErr := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, omciErr)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestMibUploadNextResponseSerializeExtendedTwoMe(t *testing.T) {
+	first := "001801150000ffe001123443215678876501010000FFBB011234000000006789"
+	second := "001801150001ffe001123443215678876501010000FFBB011234000000006789"
+	goodMessage := "02862e0b000200000040" + first + second
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0286,
+		MessageType:      MibUploadNextResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	paramData := me.ParamData{
+		EntityID: uint16(0),
+		Attributes: me.AttributeValueMap{
+			"QueueConfigurationOption":                            byte(1),
+			"MaximumQueueSize":                                    uint16(0x1234),
+			"AllocatedQueueSize":                                  uint16(0x4321),
+			"DiscardBlockCounterResetInterval":                    uint16(0x5678),
+			"ThresholdValueForDiscardedBlocksDueToBufferOverflow": uint16(0x8765),
+			"RelatedPort":                                         uint32(16842752),
+			"TrafficSchedulerPointer":                             uint16(0xFFBB),
+			"Weight":                                              byte(1),
+			"BackPressureOperation":                               uint16(0x1234),
+			"BackPressureTime":                                    uint32(0),
+			"BackPressureOccurQueueThreshold":                     uint16(0x6789),
+		},
+	}
+	reportedME, err := me.NewPriorityQueue(paramData)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+	additional := make([]me.ManagedEntity, 1)
+
+	for inst := 1; inst < 2; inst++ {
+		paramData.EntityID = uint16(inst)
+		entity, _ := me.NewPriorityQueue(paramData)
+		additional[inst-1] = *entity
+	}
+	request := &MibUploadNextResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+			Extended:       true,
+		},
+		ReportedME:    *reportedME,
+		AdditionalMEs: additional,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	omciErr := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, omciErr)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestMibUploadNextResponseSerializeExtendedThreeMe(t *testing.T) {
+	first := "001801150000ffe001123443215678876501010000FFBB011234000000006789"
+	second := "001801150001ffe001123443215678876501010000FFBB011234000000006789"
+	third := "001801150002ffe001123443215678876501010000FFBB011234000000006789"
+	goodMessage := "02862e0b000200000060" + first + second + third
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0286,
+		MessageType:      MibUploadNextResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	paramData := me.ParamData{
+		EntityID: uint16(0),
+		Attributes: me.AttributeValueMap{
+			"QueueConfigurationOption":                            byte(1),
+			"MaximumQueueSize":                                    uint16(0x1234),
+			"AllocatedQueueSize":                                  uint16(0x4321),
+			"DiscardBlockCounterResetInterval":                    uint16(0x5678),
+			"ThresholdValueForDiscardedBlocksDueToBufferOverflow": uint16(0x8765),
+			"RelatedPort":                                         uint32(16842752),
+			"TrafficSchedulerPointer":                             uint16(0xFFBB),
+			"Weight":                                              byte(1),
+			"BackPressureOperation":                               uint16(0x1234),
+			"BackPressureTime":                                    uint32(0),
+			"BackPressureOccurQueueThreshold":                     uint16(0x6789),
+		},
+	}
+	reportedME, err := me.NewPriorityQueue(paramData)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+	additional := make([]me.ManagedEntity, 2)
+
+	for inst := 1; inst < 3; inst++ {
+		paramData.EntityID = uint16(inst)
+		entity, _ := me.NewPriorityQueue(paramData)
+		additional[inst-1] = *entity
+	}
+	request := &MibUploadNextResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+			Extended:       true,
+		},
+		ReportedME:    *reportedME,
+		AdditionalMEs: additional,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	omciErr := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, omciErr)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestMibUploadNextResponseSerializeExtendedMaxFrame(t *testing.T) {
+	// Max payload after header length field and not including MIC is 1966 octets
+	maxPayloadLen := MaxExtendedLength - 10 - 4
+
+	// Payload is AttrLen (2) + ME Hdr (6) + attributes which is 30 octets
+	// below. That allows 65 'common' payloads with a remainder of 16 octets
+	// to fill with another ME
+	commonPayloadFmt := "00160115%04xffc001123443215678876501010000FFBB01123487654321"
+	lastPayload := "00080115000078001234432156788765"
+	msgHeader := fmt.Sprintf("02862e0b00020000%04x", maxPayloadLen)
+	numCommon := 65
+
+	goodMessage := msgHeader + fmt.Sprintf(commonPayloadFmt, 0)
+	for instance := 1; instance < numCommon; instance++ {
+		goodMessage += fmt.Sprintf(commonPayloadFmt, instance)
+	}
+	goodMessage += lastPayload
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0286,
+		MessageType:      MibUploadNextResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	paramData := me.ParamData{
+		EntityID: uint16(0),
+		Attributes: me.AttributeValueMap{
+			"QueueConfigurationOption":                            byte(1),
+			"MaximumQueueSize":                                    uint16(0x1234),
+			"AllocatedQueueSize":                                  uint16(0x4321),
+			"DiscardBlockCounterResetInterval":                    uint16(0x5678),
+			"ThresholdValueForDiscardedBlocksDueToBufferOverflow": uint16(0x8765),
+			"RelatedPort":                                         uint32(16842752),
+			"TrafficSchedulerPointer":                             uint16(0xFFBB),
+			"Weight":                                              byte(1),
+			"BackPressureOperation":                               uint16(0x1234),
+			"BackPressureTime":                                    uint32(0x87654321),
+		},
+	}
+	reportedME, err := me.NewPriorityQueue(paramData)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+	request := &MibUploadNextResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+			Extended:       true,
+		},
+		ReportedME:    *reportedME,
+		AdditionalMEs: make([]me.ManagedEntity, numCommon),
+	}
+	for instance := 0; instance < numCommon-1; instance++ {
+		paramData.EntityID = uint16(instance + 1)
+		reportedME, err = me.NewPriorityQueue(paramData)
+		assert.NotNil(t, err)
+		assert.Equal(t, err.StatusCode(), me.Success)
+		request.AdditionalMEs[instance] = *reportedME
+	}
+	lastMeParams := me.ParamData{
+		EntityID: uint16(0),
+		Attributes: me.AttributeValueMap{
+			"MaximumQueueSize":                                    uint16(0x1234),
+			"AllocatedQueueSize":                                  uint16(0x4321),
+			"DiscardBlockCounterResetInterval":                    uint16(0x5678),
+			"ThresholdValueForDiscardedBlocksDueToBufferOverflow": uint16(0x8765),
+		},
+	}
+	// And the last one to fully fill out the maximum sized frame
+	reportedME, err = me.NewPriorityQueue(lastMeParams)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+	request.AdditionalMEs[numCommon-1] = *reportedME
+
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	omciErr := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, omciErr)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestMibUploadNextResponseSerializeExtendedMaxFramePlusOneByteTooMany(t *testing.T) {
+	// Identical to last test but last ME has one extra octet
+	numCommon := 65
+	omciLayer := &OMCI{
+		TransactionID:    0x0286,
+		MessageType:      MibUploadNextResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	paramData := me.ParamData{
+		EntityID: uint16(0),
+		Attributes: me.AttributeValueMap{
+			"QueueConfigurationOption":                            byte(1),
+			"MaximumQueueSize":                                    uint16(0x1234),
+			"AllocatedQueueSize":                                  uint16(0x4321),
+			"DiscardBlockCounterResetInterval":                    uint16(0x5678),
+			"ThresholdValueForDiscardedBlocksDueToBufferOverflow": uint16(0x8765),
+			"RelatedPort":                                         uint32(16842752),
+			"TrafficSchedulerPointer":                             uint16(0xFFBB),
+			"Weight":                                              byte(1),
+			"BackPressureOperation":                               uint16(0x1234),
+			"BackPressureTime":                                    uint32(0x87654321),
+		},
+	}
+	reportedME, err := me.NewPriorityQueue(paramData)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+	request := &MibUploadNextResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuDataClassID,
+			EntityInstance: uint16(0),
+			Extended:       true,
+		},
+		ReportedME:    *reportedME,
+		AdditionalMEs: make([]me.ManagedEntity, numCommon),
+	}
+	for instance := 0; instance < numCommon-1; instance++ {
+		paramData.EntityID = uint16(instance + 1)
+		reportedME, err = me.NewPriorityQueue(paramData)
+		assert.NotNil(t, err)
+		assert.Equal(t, err.StatusCode(), me.Success)
+		request.AdditionalMEs[instance] = *reportedME
+	}
+	lastMeParams := me.ParamData{
+		EntityID: uint16(0),
+		Attributes: me.AttributeValueMap{
+			"QueueConfigurationOption":                            byte(1), // This is the extra byte
+			"MaximumQueueSize":                                    uint16(0x1234),
+			"AllocatedQueueSize":                                  uint16(0x4321),
+			"DiscardBlockCounterResetInterval":                    uint16(0x5678),
+			"ThresholdValueForDiscardedBlocksDueToBufferOverflow": uint16(0x8765),
+		},
+	}
+	// And the last one to fully fill out the maximum sized frame
+	reportedME, err = me.NewPriorityQueue(lastMeParams)
+	assert.NotNil(t, err)
+	assert.Equal(t, err.StatusCode(), me.Success)
+	request.AdditionalMEs[numCommon-1] = *reportedME
+
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	omciErr := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, omciErr)
+}
+
+func TestMibUploadNextResponseBadCommandNumberDecode(t *testing.T) {
+	// Test of a MIB Upload next Response that results when an invalid command number.
+	// Note that if all attributes of a managed entity do not fit within one MIB
+	// upload next response message, the attributes will be split over several
+	// messages. The OLT can use the information in the attribute mask to determine
+	// which attribute values are reported in which MIB upload next response message.
+	//TODO: Implement
+}
+
+func TestMibUploadNextResponseBadCommandNumberSerialize(t *testing.T) {
+	// Test of a MIB Upload next Response that results when an invalid command number
+	// is requested.
+	//TODO: Implement
+}
+
+func TestMibUploadNextSequence(t *testing.T) {
+	mibUploadNextSequence := [...]string{
+		"00032e0a00020000000200008000000000000000000000000000000000000000000000000000000000000028",
+		"00042e0a0002000000050101f0002f2f05202020202020202020202020202020202020202000000000000028",
+		"00052e0a00020000000501010f80202020202020202020202020202020202020202000000000000000000028",
+		"00062e0a0002000000050104f000303001202020202020202020202020202020202020202000000000000028",
+		"00072e0a00020000000501040f80202020202020202020202020202020202020202000000000000000000028",
+		"00082e0a0002000000050180f000f8f801202020202020202020202020202020202020202000000000000028",
+		"00092e0a00020000000501800f80202020202020202020202020202020202020202000000000000000000028",
+		"000a2e0a0002000000060101f0002f054252434d12345678000000000000000000000000000c000000000028",
+		"000b2e0a00020000000601010f004252434d0000000000000000000000000000000000000000000000000028",
+		"000c2e0a000200000006010100f8202020202020202020202020202020202020202000000000000000000028",
+		"000d2e0a00020000000601010004000000000000000000000000000000000000000000000000000000000028",
+		"000e2e0a0002000000060104f00030014252434d12345678000000000000000000000000000c000000000028",
+		"000f2e0a00020000000601040f004252434d0000000000000000000000000000000000000000000000000028",
+		"00102e0a000200000006010400f8202020202020202020202020202020202020202000000800000000000028",
+		"00112e0a00020000000601040004000000000000000000000000000000000000000000000000000000000028",
+		"00122e0a0002000000060180f000f8014252434d12345678000000000000000000000000000c000000000028",
+		"00132e0a00020000000601800f004252434d0000000000000000000000000000000000000000000000000028",
+		"00142e0a000200000006018000f8202020202020202020202020202020202020202000084040000000000028",
+		"00152e0a00020000000601800004000000000000000000000000000000000000000000000000000000000028",
+		"00162e0a0002000000070000f0003530323247574f3236363230303301010100000000000000000000000028",
+		"00172e0a0002000000070001f0003530323247574f3236363230303300000100000000000000000000000028",
+		"00182e0a0002000000830000c000202020202020202020202020202020202020202020202020000000000028",
+		"00192e0a00020000008300002000202020202020202020202020202000000000000000000000000000000028",
+		"001a2e0a00020000008300001000000000000000000000000000000000000000000000000000000000000028",
+		"001b2e0a0002000000850000ffe0000000000000000000000000000000000000000000000000000000000028",
+		"001c2e0a0002000000860001c00000001018aaaa000000000000000000000000000000000000000000000028",
+		"001d2e0a00020000008600012000000000000000000000000000000000000000000000000000000000000028",
+		"001e2e0a00020000008600011f80000000000000000000000000000000000000000000000000000000000028",
+		"001f2e0a00020000008600010078000000000000000000000000000000000000000000000000000000000028",
+		"00202e0a00020000008600010004000000000000000000000000000000000000000000000000000000000028",
+		"00212e0a00020000008600010002000000000000000000000000000000000000000000000000000000000028",
+		"00222e0a0002000001000000e0004252434d00000000000000000000000000004252434d1234567800000028",
+		"00232e0a00020000010000001f80000000000000000000000000000000000000000000000000000000000028",
+		"00242e0a00020000010000000040000000000000000000000000000000000000000000000000000000000028",
+		"00252e0a00020000010000000038000000000000000000000000000003000000000000000000000000000028",
+		"00262e0a0002000001010000f80042564d344b3030425241303931352d3030383300b3000001010000000028",
+		"00272e0a000200000101000007f8000000010020027c85630016000030000000000000000000000000000028",
+		"00282e0a0002000001068000e00000ff01010000000000000000000000000000000000000000000000000028",
+		"00292e0a0002000001068001e00000ff01010000000000000000000000000000000000000000000000000028",
+		"002a2e0a0002000001068002e00000ff01010000000000000000000000000000000000000000000000000028",
+		"002b2e0a0002000001068003e00000ff01010000000000000000000000000000000000000000000000000028",
+		"002c2e0a0002000001068004e00000ff01010000000000000000000000000000000000000000000000000028",
+		"002d2e0a0002000001068005e00000ff01010000000000000000000000000000000000000000000000000028",
+		"002e2e0a0002000001068006e00000ff01010000000000000000000000000000000000000000000000000028",
+		"002f2e0a0002000001068007e00000ff01010000000000000000000000000000000000000000000000000028",
+		"00302e0a0002000001078001ffff01000800300000050900000000ffff000000008181000000000000000028",
+		"00312e0a0002000001080401f000000000000401000000000000000000000000000000000000000000000028",
+		"00322e0a0002000001150401fff0000080008000000000040100000000010000000000000000000000000028",
+		"00332e0a0002000001150401000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00342e0a0002000001150402fff0000080008000000000040100010000010000000000000000000000000028",
+		"00352e0a0002000001150402000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00362e0a0002000001150403fff0000080008000000000040100020000010000000000000000000000000028",
+		"00372e0a0002000001150403000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00382e0a0002000001150404fff0000080008000000000040100030000010000000000000000000000000028",
+		"00392e0a0002000001150404000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"003a2e0a0002000001150405fff0000080008000000000040100040000010000000000000000000000000028",
+		"003b2e0a0002000001150405000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"003c2e0a0002000001150406fff0000080008000000000040100050000010000000000000000000000000028",
+		"003d2e0a0002000001150406000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"003e2e0a0002000001150407fff0000080008000000000040100060000010000000000000000000000000028",
+		"003f2e0a0002000001150407000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00402e0a0002000001150408fff0000080008000000000040100070000010000000000000000000000000028",
+		"00412e0a0002000001150408000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00422e0a0002000001158000fff0000100010000000000800000000000010000000000000000000000000028",
+		"00432e0a0002000001158000000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00442e0a0002000001158001fff0000100010000000000800000010000010000000000000000000000000028",
+		"00452e0a0002000001158001000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00462e0a0002000001158002fff0000100010000000000800000020000010000000000000000000000000028",
+		"00472e0a0002000001158002000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00482e0a0002000001158003fff0000100010000000000800000030000010000000000000000000000000028",
+		"00492e0a0002000001158003000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"004a2e0a0002000001158004fff0000100010000000000800000040000010000000000000000000000000028",
+		"004b2e0a0002000001158004000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"004c2e0a0002000001158005fff0000100010000000000800000050000010000000000000000000000000028",
+		"004d2e0a0002000001158005000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"004e2e0a0002000001158006fff0000100010000000000800000060000010000000000000000000000000028",
+		"004f2e0a0002000001158006000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00502e0a0002000001158007fff0000100010000000000800000070000010000000000000000000000000028",
+		"00512e0a0002000001158007000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00522e0a0002000001158008fff0000100010000000000800100000000010000000000000000000000000028",
+		"00532e0a0002000001158008000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00542e0a0002000001158009fff0000100010000000000800100010000010000000000000000000000000028",
+		"00552e0a0002000001158009000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00562e0a000200000115800afff0000100010000000000800100020000010000000000000000000000000028",
+		"00572e0a000200000115800a000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00582e0a000200000115800bfff0000100010000000000800100030000010000000000000000000000000028",
+		"00592e0a000200000115800b000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"005a2e0a000200000115800cfff0000100010000000000800100040000010000000000000000000000000028",
+		"005b2e0a000200000115800c000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"005c2e0a000200000115800dfff0000100010000000000800100050000010000000000000000000000000028",
+		"005d2e0a000200000115800d000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"005e2e0a000200000115800efff0000100010000000000800100060000010000000000000000000000000028",
+		"005f2e0a000200000115800e000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00602e0a000200000115800ffff0000100010000000000800100070000010000000000000000000000000028",
+		"00612e0a000200000115800f000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00622e0a0002000001158010fff0000100010000000000800200000000010000000000000000000000000028",
+		"00632e0a0002000001158010000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00642e0a0002000001158011fff0000100010000000000800200010000010000000000000000000000000028",
+		"00652e0a0002000001158011000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00662e0a0002000001158012fff0000100010000000000800200020000010000000000000000000000000028",
+		"00672e0a0002000001158012000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00682e0a0002000001158013fff0000100010000000000800200030000010000000000000000000000000028",
+		"00692e0a0002000001158013000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"006a2e0a0002000001158014fff0000100010000000000800200040000010000000000000000000000000028",
+		"006b2e0a0002000001158014000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"006c2e0a0002000001158015fff0000100010000000000800200050000010000000000000000000000000028",
+		"006d2e0a0002000001158015000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"006e2e0a0002000001158016fff0000100010000000000800200060000010000000000000000000000000028",
+		"006f2e0a0002000001158016000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00702e0a0002000001158017fff0000100010000000000800200070000010000000000000000000000000028",
+		"00712e0a0002000001158017000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00722e0a0002000001158018fff0000100010000000000800300000000010000000000000000000000000028",
+		"00732e0a0002000001158018000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00742e0a0002000001158019fff0000100010000000000800300010000010000000000000000000000000028",
+		"00752e0a0002000001158019000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00762e0a000200000115801afff0000100010000000000800300020000010000000000000000000000000028",
+		"00772e0a000200000115801a000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00782e0a000200000115801bfff0000100010000000000800300030000010000000000000000000000000028",
+		"00792e0a000200000115801b000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"007a2e0a000200000115801cfff0000100010000000000800300040000010000000000000000000000000028",
+		"007b2e0a000200000115801c000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"007c2e0a000200000115801dfff0000100010000000000800300050000010000000000000000000000000028",
+		"007d2e0a000200000115801d000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"007e2e0a000200000115801efff0000100010000000000800300060000010000000000000000000000000028",
+		"007f2e0a000200000115801e000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00802e0a000200000115801ffff0000100010000000000800300070000010000000000000000000000000028",
+		"00812e0a000200000115801f000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00822e0a0002000001158020fff0000100010000000000800400000000010000000000000000000000000028",
+		"00832e0a0002000001158020000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00842e0a0002000001158021fff0000100010000000000800400010000010000000000000000000000000028",
+		"00852e0a0002000001158021000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00862e0a0002000001158022fff0000100010000000000800400020000010000000000000000000000000028",
+		"00872e0a0002000001158022000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00882e0a0002000001158023fff0000100010000000000800400030000010000000000000000000000000028",
+		"00892e0a0002000001158023000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"008a2e0a0002000001158024fff0000100010000000000800400040000010000000000000000000000000028",
+		"008b2e0a0002000001158024000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"008c2e0a0002000001158025fff0000100010000000000800400050000010000000000000000000000000028",
+		"008d2e0a0002000001158025000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"008e2e0a0002000001158026fff0000100010000000000800400060000010000000000000000000000000028",
+		"008f2e0a0002000001158026000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00902e0a0002000001158027fff0000100010000000000800400070000010000000000000000000000000028",
+		"00912e0a0002000001158027000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00922e0a0002000001158028fff0000100010000000000800500000000010000000000000000000000000028",
+		"00932e0a0002000001158028000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00942e0a0002000001158029fff0000100010000000000800500010000010000000000000000000000000028",
+		"00952e0a0002000001158029000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00962e0a000200000115802afff0000100010000000000800500020000010000000000000000000000000028",
+		"00972e0a000200000115802a000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00982e0a000200000115802bfff0000100010000000000800500030000010000000000000000000000000028",
+		"00992e0a000200000115802b000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"009a2e0a000200000115802cfff0000100010000000000800500040000010000000000000000000000000028",
+		"009b2e0a000200000115802c000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"009c2e0a000200000115802dfff0000100010000000000800500050000010000000000000000000000000028",
+		"009d2e0a000200000115802d000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"009e2e0a000200000115802efff0000100010000000000800500060000010000000000000000000000000028",
+		"009f2e0a000200000115802e000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00a02e0a000200000115802ffff0000100010000000000800500070000010000000000000000000000000028",
+		"00a12e0a000200000115802f000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00a22e0a0002000001158030fff0000100010000000000800600000000010000000000000000000000000028",
+		"00a32e0a0002000001158030000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00a42e0a0002000001158031fff0000100010000000000800600010000010000000000000000000000000028",
+		"00a52e0a0002000001158031000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00a62e0a0002000001158032fff0000100010000000000800600020000010000000000000000000000000028",
+		"00a72e0a0002000001158032000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00a82e0a0002000001158033fff0000100010000000000800600030000010000000000000000000000000028",
+		"00a92e0a0002000001158033000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00aa2e0a0002000001158034fff0000100010000000000800600040000010000000000000000000000000028",
+		"00ab2e0a0002000001158034000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00ac2e0a0002000001158035fff0000100010000000000800600050000010000000000000000000000000028",
+		"00ad2e0a0002000001158035000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00ae2e0a0002000001158036fff0000100010000000000800600060000010000000000000000000000000028",
+		"00af2e0a0002000001158036000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00b02e0a0002000001158037fff0000100010000000000800600070000010000000000000000000000000028",
+		"00b12e0a0002000001158037000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00b22e0a0002000001158038fff0000100010000000000800700000000010000000000000000000000000028",
+		"00b32e0a0002000001158038000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00b42e0a0002000001158039fff0000100010000000000800700010000010000000000000000000000000028",
+		"00b52e0a0002000001158039000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00b62e0a000200000115803afff0000100010000000000800700020000010000000000000000000000000028",
+		"00b72e0a000200000115803a000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00b82e0a000200000115803bfff0000100010000000000800700030000010000000000000000000000000028",
+		"00b92e0a000200000115803b000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00ba2e0a000200000115803cfff0000100010000000000800700040000010000000000000000000000000028",
+		"00bb2e0a000200000115803c000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00bc2e0a000200000115803dfff0000100010000000000800700050000010000000000000000000000000028",
+		"00bd2e0a000200000115803d000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00be2e0a000200000115803efff0000100010000000000800700060000010000000000000000000000000028",
+		"00bf2e0a000200000115803e000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00c02e0a000200000115803ffff0000100010000000000800700070000010000000000000000000000000028",
+		"00c12e0a000200000115803f000f0200020002000200ffff0900000000000000000000000000000000000028",
+		"00c22e0a0002000001168000f000800000000200000000000000000000000000000000000000000000000028",
+		"00c32e0a0002000001168001f000800000000200000000000000000000000000000000000000000000000028",
+		"00c42e0a0002000001168002f000800000000200000000000000000000000000000000000000000000000028",
+		"00c52e0a0002000001168003f000800000000200000000000000000000000000000000000000000000000028",
+		"00c62e0a0002000001168004f000800000000200000000000000000000000000000000000000000000000028",
+		"00c72e0a0002000001168005f000800000000200000000000000000000000000000000000000000000000028",
+		"00c82e0a0002000001168006f000800000000200000000000000000000000000000000000000000000000028",
+		"00c92e0a0002000001168007f000800000000200000000000000000000000000000000000000000000000028",
+		"00ca2e0a0002000001168008f000800100000200000000000000000000000000000000000000000000000028",
+		"00cb2e0a0002000001168009f000800100000200000000000000000000000000000000000000000000000028",
+		"00cc2e0a000200000116800af000800100000200000000000000000000000000000000000000000000000028",
+		"00cd2e0a000200000116800bf000800100000200000000000000000000000000000000000000000000000028",
+		"00ce2e0a000200000116800cf000800100000200000000000000000000000000000000000000000000000028",
+		"00cf2e0a000200000116800df000800100000200000000000000000000000000000000000000000000000028",
+		"00d02e0a000200000116800ef000800100000200000000000000000000000000000000000000000000000028",
+		"00d12e0a000200000116800ff000800100000200000000000000000000000000000000000000000000000028",
+		"00d22e0a0002000001168010f000800200000200000000000000000000000000000000000000000000000028",
+		"00d32e0a0002000001168011f000800200000200000000000000000000000000000000000000000000000028",
+		"00d42e0a0002000001168012f000800200000200000000000000000000000000000000000000000000000028",
+		"00d52e0a0002000001168013f000800200000200000000000000000000000000000000000000000000000028",
+		"00d62e0a0002000001168014f000800200000200000000000000000000000000000000000000000000000028",
+		"00d72e0a0002000001168015f000800200000200000000000000000000000000000000000000000000000028",
+		"00d82e0a0002000001168016f000800200000200000000000000000000000000000000000000000000000028",
+		"00d92e0a0002000001168017f000800200000200000000000000000000000000000000000000000000000028",
+		"00da2e0a0002000001168018f000800300000200000000000000000000000000000000000000000000000028",
+		"00db2e0a0002000001168019f000800300000200000000000000000000000000000000000000000000000028",
+		"00dc2e0a000200000116801af000800300000200000000000000000000000000000000000000000000000028",
+		"00dd2e0a000200000116801bf000800300000200000000000000000000000000000000000000000000000028",
+		"00de2e0a000200000116801cf000800300000200000000000000000000000000000000000000000000000028",
+		"00df2e0a000200000116801df000800300000200000000000000000000000000000000000000000000000028",
+		"00e02e0a000200000116801ef000800300000200000000000000000000000000000000000000000000000028",
+		"00e12e0a000200000116801ff000800300000200000000000000000000000000000000000000000000000028",
+		"00e22e0a0002000001168020f000800400000200000000000000000000000000000000000000000000000028",
+		"00e32e0a0002000001168021f000800400000200000000000000000000000000000000000000000000000028",
+		"00e42e0a0002000001168022f000800400000200000000000000000000000000000000000000000000000028",
+		"00e52e0a0002000001168023f000800400000200000000000000000000000000000000000000000000000028",
+		"00e62e0a0002000001168024f000800400000200000000000000000000000000000000000000000000000028",
+		"00e72e0a0002000001168025f000800400000200000000000000000000000000000000000000000000000028",
+		"00e82e0a0002000001168026f000800400000200000000000000000000000000000000000000000000000028",
+		"00e92e0a0002000001168027f000800400000200000000000000000000000000000000000000000000000028",
+		"00ea2e0a0002000001168028f000800500000200000000000000000000000000000000000000000000000028",
+		"00eb2e0a0002000001168029f000800500000200000000000000000000000000000000000000000000000028",
+		"00ec2e0a000200000116802af000800500000200000000000000000000000000000000000000000000000028",
+		"00ed2e0a000200000116802bf000800500000200000000000000000000000000000000000000000000000028",
+		"00ee2e0a000200000116802cf000800500000200000000000000000000000000000000000000000000000028",
+		"00ef2e0a000200000116802df000800500000200000000000000000000000000000000000000000000000028",
+		"00f02e0a000200000116802ef000800500000200000000000000000000000000000000000000000000000028",
+		"00f12e0a000200000116802ff000800500000200000000000000000000000000000000000000000000000028",
+		"00f22e0a0002000001168030f000800600000200000000000000000000000000000000000000000000000028",
+		"00f32e0a0002000001168031f000800600000200000000000000000000000000000000000000000000000028",
+		"00f42e0a0002000001168032f000800600000200000000000000000000000000000000000000000000000028",
+		"00f52e0a0002000001168033f000800600000200000000000000000000000000000000000000000000000028",
+		"00f62e0a0002000001168034f000800600000200000000000000000000000000000000000000000000000028",
+		"00f72e0a0002000001168035f000800600000200000000000000000000000000000000000000000000000028",
+		"00f82e0a0002000001168036f000800600000200000000000000000000000000000000000000000000000028",
+		"00f92e0a0002000001168037f000800600000200000000000000000000000000000000000000000000000028",
+		"00fa2e0a0002000001168038f000800700000200000000000000000000000000000000000000000000000028",
+		"00fb2e0a0002000001168039f000800700000200000000000000000000000000000000000000000000000028",
+		"00fc2e0a000200000116803af000800700000200000000000000000000000000000000000000000000000028",
+		"00fd2e0a000200000116803bf000800700000200000000000000000000000000000000000000000000000028",
+		"00fe2e0a000200000116803cf000800700000200000000000000000000000000000000000000000000000028",
+		"00ff2e0a000200000116803df000800700000200000000000000000000000000000000000000000000000028",
+		"01002e0a000200000116803ef000800700000200000000000000000000000000000000000000000000000028",
+		"01012e0a000200000116803ff000800700000200000000000000000000000000000000000000000000000028",
+		"01022e0a0002000001490401c000000000000000000000000000000000000000000000000000000000000028",
+		"01032e0a00020000014904012000000000000000000000000000000000000000000000000000000000000028",
+		"01042e0a00020000014904011800ffffffff0000000000000000000000000000000000000000000000000028",
+	}
+	firstTid := uint16(3)
+
+	for _, packetString := range mibUploadNextSequence {
+		data, err := stringToPacket(packetString)
+		assert.NoError(t, err)
+
+		packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+		assert.NotNil(t, packet)
+
+		omciLayer := packet.Layer(LayerTypeOMCI)
+		assert.NotNil(t, omciLayer)
+
+		omciMsg, ok := omciLayer.(*OMCI)
+		assert.True(t, ok)
+		assert.Equal(t, firstTid, omciMsg.TransactionID)
+		assert.Equal(t, MibUploadNextResponseType, omciMsg.MessageType)
+		assert.Equal(t, uint16(40), omciMsg.Length)
+
+		msgLayer := packet.Layer(LayerTypeMibUploadNextResponse)
+		assert.NotNil(t, msgLayer)
+
+		uploadResponse, ok2 := msgLayer.(*MibUploadNextResponse)
+		assert.True(t, ok2)
+		assert.Equal(t, me.OnuDataClassID, uploadResponse.EntityClass)
+		assert.Equal(t, uint16(0), uploadResponse.EntityInstance)
+
+		// Test serialization back to former string
+		var options gopacket.SerializeOptions
+		options.FixLengths = true
+
+		buffer := gopacket.NewSerializeBuffer()
+		err = gopacket.SerializeLayers(buffer, options, omciMsg, uploadResponse)
+		assert.NoError(t, err)
+
+		outgoingPacket := buffer.Bytes()
+		reconstituted := packetToString(outgoingPacket)
+		assert.Equal(t, strings.ToLower(packetString), reconstituted)
+
+		// Advance TID
+		firstTid += 1
+	}
+}
+
+// TestUnsupportedG988ClassIDMibUploadNextResponse tests decoding of an Unknown class ID that is
+// in the range of IDs assigned for G.988 use
+func TestUnsupportedG988ClassIDMibUploadNextResponse(t *testing.T) {
+	// The unsupported G.988 class ID below is 37 (0x0025), which is marked in the G.988
+	// (11/2017) as 'Intentionally left blank).  The encoded frame is a Get-Next
+	// response with a single attribute 1 & 16 (0x8001) encoded.
+	//
+	tid := 3
+	cid := 0x25
+	eid := 1
+	mask := 0x8000
+	omci_hdr := "00032e0a"
+	msg_hdr := "00020000"
+	reported_me_hdr := "002500018000"
+	attr := "0102030405060708090A0B0C0D0E0F101112131415161718191A"
+	trailer := "0000002828ce00e2"
+	msg := omci_hdr + msg_hdr + reported_me_hdr + attr + trailer
+	data, err := stringToPacket(msg)
+	assert.NoError(t, err)
+
+	// Decode packet (lazy this time)
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.Lazy)
+	assert.NotNil(t, packet)
+
+	// OMCI Layer Contents are the
+	//   - TCI          (2 bytes)
+	//   - Msg Type     (1 byte)
+	//   - Device Ident (1 byte)
+	//
+	// payload is remaining layers (less optional length and MIC)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, packet)
+
+	contents := omciLayer.LayerContents()
+	payload := omciLayer.LayerPayload()
+	assert.NotNil(t, contents)
+	assert.NotNil(t, payload)
+	assert.Equal(t, len(contents), len(omci_hdr)/2)
+	assert.Equal(t, len(payload), len(msg_hdr+reported_me_hdr+attr)/2)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, uint16(tid), omciMsg.TransactionID)
+	assert.Equal(t, MibUploadNextResponseType, omciMsg.MessageType)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	// Message Layer contents for a MIB upload next response (baseline message set) are the
+	//    - OMCI Message Header (TCI, msg Type, ...)  (4 bytes)
+	//
+	// Message Layer payload for a MIB upload next response are the
+	//    - ONU Data Class/Instance                   (4 bytes)
+	//    - Reported Managed Entity Class/Instance    (4 bytes)
+	//    - Attribute Mask                            (2 bytes)
+	//    - Attributes
+	//      and zero-padding (but not length & MIC)
+
+	msgLayer := packet.Layer(LayerTypeMibUploadNextResponse)
+	assert.NotNil(t, msgLayer)
+
+	contents = msgLayer.LayerContents()
+	payload = msgLayer.LayerPayload()
+	assert.NotNil(t, contents)
+	assert.NotNil(t, payload)
+	assert.Equal(t, len(msg_hdr)/2, len(contents))
+	assert.Equal(t, len(reported_me_hdr+attr)/2, len(payload))
+
+	uploadResponse, ok2 := msgLayer.(*MibUploadNextResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, uploadResponse)
+
+	assert.Equal(t, me.OnuDataClassID, uploadResponse.EntityClass)
+	assert.Equal(t, uint16(0), uploadResponse.EntityInstance)
+	assert.Equal(t, me.ClassID(cid), uploadResponse.ReportedME.GetClassID())
+	assert.Equal(t, uint16(eid), uploadResponse.ReportedME.GetEntityID())
+	assert.Equal(t, uint16(mask), uploadResponse.ReportedME.GetAttributeMask())
+
+	name := "UnknownAttr_1"
+	blobAttribute, err := uploadResponse.ReportedME.GetAttribute(name)
+	assert.Nil(t, err)
+	assert.NotNil(t, blobAttribute)
+}
+
+func TestUnsupportedG988ClassIDMibUploadNextResponseAttributes(t *testing.T) {
+	// Same as previous, but try different attribute mask combinations
+	tid := 3
+	cid := 0x25
+	eid := 1
+
+	// There are a number of ranges for vendor ID use. List below picks one from
+	// each of those ranges
+	masks := []uint16{0x8001, 0x0000, 0x0001, 0x8000}
+
+	trailer := "0000002828ce00e2"
+	attr := "0102030405060708090A0B0C0D0E0F101112131415161718191A"
+
+	for _, mask := range masks {
+		hdr := fmt.Sprintf("00032e0a0002000000250001%04x", mask)
+
+		msg := hdr + attr + trailer
+		data, err := stringToPacket(msg)
+		assert.NoError(t, err)
+
+		packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+		assert.NotNil(t, packet)
+
+		omciLayer := packet.Layer(LayerTypeOMCI)
+		assert.NotNil(t, packet)
+
+		omciMsg, ok := omciLayer.(*OMCI)
+		assert.True(t, ok)
+		assert.Equal(t, uint16(tid), omciMsg.TransactionID)
+		assert.Equal(t, MibUploadNextResponseType, omciMsg.MessageType)
+		assert.Equal(t, uint16(40), omciMsg.Length)
+
+		msgLayer := packet.Layer(LayerTypeMibUploadNextResponse)
+		assert.NotNil(t, msgLayer)
+
+		uploadResponse, ok2 := msgLayer.(*MibUploadNextResponse)
+		assert.True(t, ok2)
+		assert.NotNil(t, uploadResponse)
+		assert.Equal(t, me.OnuDataClassID, uploadResponse.EntityClass)
+		assert.Equal(t, uint16(0), uploadResponse.EntityInstance)
+		assert.Equal(t, me.ClassID(cid), uploadResponse.ReportedME.GetClassID())
+		assert.Equal(t, uint16(eid), uploadResponse.ReportedME.GetEntityID())
+		assert.Equal(t, mask, uploadResponse.ReportedME.GetAttributeMask())
+	}
+}
+
+// TestUnsupportedVendorClassIDMibUploadNextResponse tests decoding of an Unknown class ID that is
+// in the range of IDs assigned for vendor assignment
+func TestUnsupportedVendorClassIDMibUploadNextResponse(t *testing.T) {
+	tid := 3
+	eid := 0
+	mask := 0x8000
+
+	// There are a number of ranges for vendor ID use. List below picks one from
+	// each of those ranges
+	classIDs := []uint16{250, 355, 65500}
+
+	hdr := "00032e0a00020000"
+	attr := "0102030405060708090A0B0C0D0E0F101112131415161718191A"
+	trailer := "0000002828ce00e2"
+
+	for _, cid := range classIDs {
+		cidToMask := fmt.Sprintf("%04x%04x%04x", cid, eid, mask)
+		msg := hdr + cidToMask + attr + trailer
+		data, err := stringToPacket(msg)
+		assert.NoError(t, err)
+
+		packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+		assert.NotNil(t, packet)
+
+		omciLayer := packet.Layer(LayerTypeOMCI)
+		assert.NotNil(t, packet)
+
+		omciMsg, ok := omciLayer.(*OMCI)
+		assert.True(t, ok)
+		assert.Equal(t, uint16(tid), omciMsg.TransactionID)
+		assert.Equal(t, MibUploadNextResponseType, omciMsg.MessageType)
+		assert.Equal(t, uint16(40), omciMsg.Length)
+
+		msgLayer := packet.Layer(LayerTypeMibUploadNextResponse)
+		assert.NotNil(t, msgLayer)
+
+		uploadResponse, ok2 := msgLayer.(*MibUploadNextResponse)
+		assert.True(t, ok2)
+		assert.NotNil(t, uploadResponse)
+		assert.Equal(t, me.OnuDataClassID, uploadResponse.EntityClass)
+		assert.Equal(t, uint16(0), uploadResponse.EntityInstance)
+		assert.Equal(t, me.ClassID(cid), uploadResponse.ReportedME.GetClassID())
+		assert.Equal(t, uint16(eid), uploadResponse.ReportedME.GetEntityID())
+		assert.Equal(t, uint16(mask), uploadResponse.ReportedME.GetAttributeMask())
+
+		name := "UnknownAttr_1"
+		blobAttribute, err := uploadResponse.ReportedME.GetAttribute(name)
+
+		assert.Nil(t, err)
+		assert.NotNil(t, blobAttribute)
+
+		byteValue, ok3 := blobAttribute.([]uint8)
+		assert.True(t, ok3)
+		assert.NotNil(t, byteValue)
+	}
+}
+
+func TestMibUpload(t *testing.T) {
+	mibUpload := "00304D0A000200000000000000000000" +
+		"00000000000000000000000000000000" +
+		"000000000000000000000028"
+
+	data, err := stringToPacket(mibUpload)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, packet)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, uint16(0x30), omciMsg.TransactionID)
+	assert.Equal(t, MibUploadRequestType, omciMsg.MessageType)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeMibUploadRequest)
+	assert.NotNil(t, msgLayer)
+
+	uploadRequest, ok2 := msgLayer.(*MibUploadRequest)
+	assert.True(t, ok2)
+	assert.Equal(t, me.OnuDataClassID, uploadRequest.EntityClass)
+	assert.Equal(t, uint16(0), uploadRequest.EntityInstance)
+
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err = gopacket.SerializeLayers(buffer, options, omciMsg, uploadRequest)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(mibUpload), reconstituted)
+}
diff --git a/omci.go b/omci.go
index 2f6d2d9..75b1e41 100644
--- a/omci.go
+++ b/omci.go
@@ -33,7 +33,7 @@
 // DeviceIdent identifies the OMCI message format. Currently either baseline or extended.
 type DeviceIdent byte
 
-// LayerTypeOmci provide a gopacket LayerType for OMCI messages
+// LayerTypeOMCI provides a gopacket LayerType for OMCI messages
 var (
 	LayerTypeOMCI gopacket.LayerType
 )
@@ -53,7 +53,7 @@
 	// G-PON OLTs and ONUs support the baseline message set
 	BaselineIdent DeviceIdent = 0x0A
 
-	// ExtendedIdent messager are up to 1920 octets but may not be supported by all ONUs or OLTs.
+	// ExtendedIdent messages are up to 1920 octets but may not be supported by all ONUs or OLTs.
 	ExtendedIdent DeviceIdent = 0x0B
 )
 
@@ -136,12 +136,6 @@
 }
 
 func (omci *OMCI) String() string {
-	//msgType := me.MsgType(byte(omci.MessageType) & me.MsgTypeMask)
-	//if me.IsAutonomousNotification(msgType) {
-	//	return fmt.Sprintf("OMCI: Type: %v:", msgType)
-	//} else if byte(omci.MessageType)&me.AK == me.AK {
-	//	return fmt.Sprintf("OMCI: Type: %v Response", msgType)
-	//}
 	return fmt.Sprintf("Type: %v, TID: %d (%#x), Ident: %v",
 		omci.MessageType, omci.TransactionID, omci.TransactionID, omci.DeviceIdentifier)
 }
@@ -151,6 +145,19 @@
 	return LayerTypeOMCI
 }
 
+// CanDecode returns the layers that this class can decode
+func (omci *OMCI) CanDecode() gopacket.LayerClass {
+	return LayerTypeOMCI
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *OMCI) NextLayerType() gopacket.LayerType {
+	if next, ok := nextLayerMapping[omci.MessageType]; ok {
+		return next
+	}
+	return gopacket.LayerTypePayload
+}
+
 // LayerContents returns the OMCI specific layer information
 func (omci *OMCI) LayerContents() []byte {
 	b := make([]byte, 4)
@@ -160,19 +167,9 @@
 	return b
 }
 
-// CanDecode returns the layers that this class can decode
-func (omci *OMCI) CanDecode() gopacket.LayerClass {
-	return LayerTypeOMCI
-}
-
-// NextLayerType returns the layer type contained by this DecodingLayer.
-func (omci *OMCI) NextLayerType() gopacket.LayerType {
-	return gopacket.LayerTypeZero
-}
-
 func decodeOMCI(data []byte, p gopacket.PacketBuilder) error {
 	// Allow baseline messages without Length & MIC, but no less
-	if len(data) < 10 {
+	if len(data) < 4 {
 		p.SetTruncated()
 		return errors.New("frame header too small")
 	}
@@ -185,11 +182,17 @@
 	case BaselineIdent:
 		if len(data) < MaxBaselineLength-8 {
 			p.SetTruncated()
-			return errors.New("frame too small")
+			return fmt.Errorf("frame too small. OMCI baseline frame length %v, %v required",
+				len(data), MaxBaselineLength-8)
 		}
 		return omci.DecodeFromBytes(data, p)
 
 	case ExtendedIdent:
+		if len(data) < 10 {
+			p.SetTruncated()
+			return fmt.Errorf("frame too small. OMCI minimal extended frame length %v, 10 required",
+				len(data))
+		}
 		return omci.DecodeFromBytes(data, p)
 	}
 }
@@ -219,10 +222,7 @@
 
 // DecodeFromBytes will decode the OMCI layer of a packet/message
 func (omci *OMCI) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
-	if len(data) < 10 {
-		p.SetTruncated()
-		return errors.New("frame too small")
-	}
+	// Minimal Baseline and Extended message set length has already been checked
 	omci.TransactionID = binary.BigEndian.Uint16(data[0:])
 	omci.MessageType = MessageType(data[2])
 	omci.DeviceIdentifier = DeviceIdent(data[3])
@@ -272,7 +272,10 @@
 			//return errors.New(msg)
 		}
 	}
-	omci.BaseLayer = layers.BaseLayer{data[:4], data[4:eomOffset]}
+	omci.BaseLayer = layers.BaseLayer{
+		Contents: data[:4],
+		Payload:  data[4:eomOffset],
+	}
 	p.AddLayer(omci)
 	nextLayer, err := MsgTypeToNextLayer(omci.MessageType, omci.DeviceIdentifier == ExtendedIdent)
 	if err != nil {
@@ -290,10 +293,16 @@
 		return err
 	}
 	// OMCI layer error checks
-	isNotification := (int(omci.MessageType) & ^me.MsgTypeMask) == 0
-	if omci.TransactionID == 0 && !isNotification {
+	// Self-initiated Test Results have a TID of 0, OLT-requested do not.
+	isNotification := omci.MessageType == AlarmNotificationType ||
+		omci.MessageType == AttributeValueChangeType
+
+	if omci.TransactionID == 0 && !isNotification && omci.MessageType != TestResultType {
 		return errors.New("omci Transaction ID is zero for non-Notification type message")
 	}
+	if omci.TransactionID != 0 && isNotification {
+		return errors.New("omci Transaction ID is not zero for Notification type message")
+	}
 	if omci.DeviceIdentifier == 0 {
 		omci.DeviceIdentifier = BaselineIdent // Allow uninitialized device identifier
 	}
diff --git a/omci_test.go b/omci_test.go
index b383881..86c9a59 100644
--- a/omci_test.go
+++ b/omci_test.go
@@ -28,6 +28,51 @@
 	"testing"
 )
 
+var allBaselineTypes = []MessageType{
+	CreateRequestType,
+	CreateResponseType,
+	DeleteRequestType,
+	DeleteResponseType,
+	SetRequestType,
+	SetResponseType,
+	GetRequestType,
+	GetResponseType,
+	GetAllAlarmsRequestType,
+	GetAllAlarmsResponseType,
+	GetAllAlarmsNextRequestType,
+	GetAllAlarmsNextResponseType,
+	MibUploadRequestType,
+	MibUploadResponseType,
+	MibUploadNextRequestType,
+	MibUploadNextResponseType,
+	MibResetRequestType,
+	MibResetResponseType,
+	TestRequestType,
+	TestResponseType,
+	StartSoftwareDownloadRequestType,
+	StartSoftwareDownloadResponseType,
+	DownloadSectionRequestType,
+	DownloadSectionRequestWithResponseType,
+	DownloadSectionResponseType,
+	EndSoftwareDownloadRequestType,
+	EndSoftwareDownloadResponseType,
+	ActivateSoftwareRequestType,
+	ActivateSoftwareResponseType,
+	CommitSoftwareRequestType,
+	CommitSoftwareResponseType,
+	SynchronizeTimeRequestType,
+	SynchronizeTimeResponseType,
+	RebootRequestType,
+	RebootResponseType,
+	GetNextRequestType,
+	GetNextResponseType,
+	GetCurrentDataRequestType,
+	GetCurrentDataResponseType,
+	AlarmNotificationType,
+	AttributeValueChangeType,
+	TestResultType,
+}
+
 func stringToPacket(input string) ([]byte, error) {
 	var p []byte
 
@@ -73,48 +118,11 @@
 	assert.NotEqual(t, unknownString, extendedString)
 }
 
-// MibResetRequestTest tests decode/encode of a MIB Reset Request
-func TestMibResetRequestMessage(t *testing.T) {
-	mibResetRequest := "00014F0A000200000000000000000000" +
-		"00000000000000000000000000000000" +
-		"000000000000000000000028"
+func TestOmciCanDecodeAndNextLayer(t *testing.T) {
 
-	data, err := stringToPacket(mibResetRequest)
-	assert.NoError(t, err)
+	baselineString := BaselineIdent.String()
+	assert.NotZero(t, len(baselineString))
 
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, packet)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(1))
-	assert.Equal(t, omciMsg.MessageType, MibResetRequestType)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeMibResetRequest)
-	assert.NotNil(t, msgLayer)
-
-	omciMsg2, ok2 := msgLayer.(*MibResetRequest)
-	assert.True(t, ok2)
-	assert.Equal(t, omciMsg2.EntityClass, OnuDataClassID)
-	assert.Equal(t, omciMsg2.EntityInstance, uint16(0))
-
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err = gopacket.SerializeLayers(buffer, options, omciMsg, omciMsg2)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(mibResetRequest), reconstituted)
-}
-
-func TestCreateGalEthernetProfile(t *testing.T) {
 	createGalEthernetProfile := "0002440A011000010030000000000000" +
 		"00000000000000000000000000000000" +
 		"000000000000000000000028"
@@ -130,1206 +138,144 @@
 
 	omciMsg, ok := omciLayer.(*OMCI)
 	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(2))
-	assert.Equal(t, omciMsg.MessageType, CreateRequestType)
-	assert.Equal(t, omciMsg.Length, uint16(40))
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeCreateRequest, omciMsg.NextLayerType())
 
 	msgLayer := packet.Layer(LayerTypeCreateRequest)
 	assert.NotNil(t, msgLayer)
 
 	omciMsg2, ok2 := msgLayer.(*CreateRequest)
 	assert.True(t, ok2)
-	assert.Equal(t, omciMsg2.EntityClass, GalEthernetProfileClassID)
-	assert.Equal(t, omciMsg2.EntityInstance, uint16(1))
-
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err = gopacket.SerializeLayers(buffer, options, omciMsg, omciMsg2)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(createGalEthernetProfile), reconstituted)
+	assert.Equal(t, LayerTypeCreateRequest, omciMsg2.LayerType())
+	assert.Equal(t, LayerTypeCreateRequest, omciMsg2.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, omciMsg2.NextLayerType())
 }
 
-func TestSetTCont(t *testing.T) {
-	setTCont := "0003480A010680008000040000000000" +
-		"00000000000000000000000000000000" +
-		"000000000000000000000028"
-
-	data, err := stringToPacket(setTCont)
+func TestOmciHeaderVeryShort(t *testing.T) {
+	// Need at least 6 octets in OMCI header to decode Message Type
+	message := "000159"
+	data, err := stringToPacket(message)
 	assert.NoError(t, err)
 
 	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
 	assert.NotNil(t, packet)
 
 	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, packet)
+	assert.Nil(t, omciLayer)
 
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(3))
-	assert.Equal(t, omciMsg.MessageType, SetRequestType)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeSetRequest)
-	assert.NotNil(t, msgLayer)
-
-	omciMsg2, ok2 := msgLayer.(*SetRequest)
-	assert.True(t, ok2)
-	assert.Equal(t, omciMsg2.EntityClass, TContClassID)
-	assert.Equal(t, omciMsg2.EntityInstance, uint16(0x8000))
-
-	attributes := omciMsg2.Attributes
-	assert.Equal(t, len(attributes), 2)
-
-	// TODO: Create generic test to look up the name from definition
-	// Here 1 is the index in the attribute definition map of a TCONT that points
-	// to the AllocID attribute.
-	value, ok3 := attributes["AllocId"]
-	assert.True(t, ok3)
-	assert.Equal(t, value, uint16(1024))
-
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err = gopacket.SerializeLayers(buffer, options, omciMsg, omciMsg2)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(setTCont), reconstituted)
+	badLayer := packet.Layer(gopacket.LayerTypeDecodeFailure)
+	assert.NotNil(t, badLayer)
+	assert.True(t, packet.Metadata().Truncated)
 }
 
-func TestCreate8021pMapperService_profile(t *testing.T) {
-	create8021pMapperServiceProfile := "0007440A00828000ffffffffffffffff" +
-		"ffffffffffffffffffff000000000000" +
-		"000000000000000000000028"
-
-	data, err := stringToPacket(create8021pMapperServiceProfile)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, packet)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(7))
-	assert.Equal(t, omciMsg.MessageType, CreateRequestType)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeCreateRequest)
-	assert.NotNil(t, msgLayer)
-
-	createRequest, ok2 := msgLayer.(*CreateRequest)
-	assert.True(t, ok2)
-	assert.Equal(t, createRequest.EntityClass, Ieee8021PMapperServiceProfileClassID)
-	assert.Equal(t, createRequest.EntityInstance, uint16(0x8000))
-
-	attributes := createRequest.Attributes
-	assert.NotNil(t, attributes)
-	assert.Equal(t, len(attributes), 13)
-
-	// As this is a create request, gather up all set-by-create attributes
-	// make sure we got them all, and nothing else
-	meDefinition, omciErr := LoadManagedEntityDefinition(createRequest.EntityClass)
-	assert.NotNil(t, omciErr)
-	assert.Equal(t, omciErr.StatusCode(), Success)
-
-	attrDefs := meDefinition.GetAttributeDefinitions()
-
-	for index := uint(1); index <= uint(9); index++ {
-		attrName := attrDefs[index].GetName()
-		value, ok := attributes[attrName]
-		assert.True(t, ok)
-
-		value16, ok3 := value.(uint16)
-		assert.True(t, ok3)
-		assert.Equal(t, value16, uint16(0xffff))
-	}
-
-	sbcMask := getSbcMask(meDefinition)
-	for index := uint(1); index < uint(len(attrDefs)); index++ {
-		attrName := attrDefs[index].GetName()
-
-		if sbcMask&uint16(1<<(uint)(16-index)) != 0 {
-			_, ok3 := attributes[attrName]
-			assert.True(t, ok3)
-		} else {
-			_, ok3 := attributes[attrName]
-			assert.False(t, ok3)
+func TestOmciHeaderBaselineShort(t *testing.T) {
+	for _, msgType := range allBaselineTypes {
+		// Smallest message baseline is 40 bytes (length and MIC optional)
+		tid := 1
+		if msgType == AlarmNotificationType || msgType == AttributeValueChangeType {
+			tid = 0
 		}
-	}
-	// TODO: Individual attribute tests here if needed
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
+		msg39 := fmt.Sprintf("%04x%02x0a0002000000000000000000000000000000000000000000000000000000000000000000",
+			uint16(tid), uint8(msgType))
 
-	buffer := gopacket.NewSerializeBuffer()
-	err = gopacket.SerializeLayers(buffer, options, omciMsg, createRequest)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(create8021pMapperServiceProfile), reconstituted)
-}
-
-func TestCreate_macBridgeService_profile(t *testing.T) {
-	var createMacBridgeServiceProfile = "000B440A002D02010001008000140002" +
-		"000f0001000000000000000000000000" +
-		"000000000000000000000028"
-
-	data, err := stringToPacket(createMacBridgeServiceProfile)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, packet)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0xb))
-	assert.Equal(t, omciMsg.MessageType, CreateRequestType)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeCreateRequest)
-	assert.NotNil(t, msgLayer)
-
-	createRequest, ok2 := msgLayer.(*CreateRequest)
-	assert.True(t, ok2)
-	assert.Equal(t, createRequest.EntityClass, MacBridgeServiceProfileClassID)
-	assert.Equal(t, createRequest.EntityInstance, uint16(0x201))
-
-	attributes := createRequest.Attributes
-	assert.NotNil(t, attributes)
-
-	// As this is a create request, gather up all set-by-create attributes
-	// make sure we got them all, and nothing else
-	meDefinition, omciErr := LoadManagedEntityDefinition(createRequest.EntityClass)
-	assert.NotNil(t, omciErr)
-	assert.Equal(t, omciErr.StatusCode(), Success)
-
-	attrDefs := meDefinition.GetAttributeDefinitions()
-
-	sbcMask := getSbcMask(meDefinition)
-	for index := uint(1); index < uint(len(attrDefs)); index++ {
-		attrName := attrDefs[index].GetName()
-
-		if sbcMask&uint16(1<<(uint)(16-index)) != 0 {
-			_, ok3 := attributes[attrName]
-			assert.True(t, ok3)
-		} else {
-			_, ok3 := attributes[attrName]
-			assert.False(t, ok3)
-		}
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err = gopacket.SerializeLayers(buffer, options, omciMsg, createRequest)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(createMacBridgeServiceProfile), reconstituted)
-}
-
-func TestCreateGemPortNetworkCtp(t *testing.T) {
-	createGemPortNetworkCtp := "000C440A010C01000400800003010000" +
-		"00000000000000000000000000000000" +
-		"000000000000000000000028"
-
-	data, err := stringToPacket(createGemPortNetworkCtp)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, packet)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0xc))
-	assert.Equal(t, omciMsg.MessageType, CreateRequestType)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeCreateRequest)
-	assert.NotNil(t, msgLayer)
-
-	createRequest, ok2 := msgLayer.(*CreateRequest)
-	assert.True(t, ok2)
-	assert.Equal(t, createRequest.EntityClass, GemPortNetworkCtpClassID)
-	assert.Equal(t, createRequest.EntityInstance, uint16(0x100))
-
-	attributes := createRequest.Attributes
-	assert.NotNil(t, attributes)
-
-	// As this is a create request, gather up all set-by-create attributes
-	// make sure we got them all, and nothing else
-	meDefinition, omciErr := LoadManagedEntityDefinition(createRequest.EntityClass)
-	assert.NotNil(t, omciErr)
-	assert.Equal(t, omciErr.StatusCode(), Success)
-
-	attrDefs := meDefinition.GetAttributeDefinitions()
-
-	sbcMask := getSbcMask(meDefinition)
-	for index := uint(1); index < uint(len(attrDefs)); index++ {
-		attrName := attrDefs[index].GetName()
-
-		if sbcMask&uint16(1<<(uint)(16-index)) != 0 {
-			_, ok3 := attributes[attrName]
-			assert.True(t, ok3)
-		} else {
-			_, ok3 := attributes[attrName]
-			assert.False(t, ok3)
-		}
-	}
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err = gopacket.SerializeLayers(buffer, options, omciMsg, createRequest)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(createGemPortNetworkCtp), reconstituted)
-}
-
-// TODO: Uncomment as encode/decode supported
-//func TestMulticastGemInterworkingTp(t *testing.T) {
-//
-//	multicastGemInterworkingTp := "0011440A011900060104000001000000" +
-//		"00000000000000000000000000000000" +
-//		"000000000000000000000028"
-//
-//	data, err := stringToPacket(multicastGemInterworkingTp)
-//	assert.NoError(t, err)
-//
-//	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-//	fmt.Println(packet)
-//
-//	customLayer := packet.Layer(LayerTypeOMCI)
-//	assert.NotNil(t, customLayer)
-//}
-//
-//func TestCreateGemInteworkingTp(t *testing.T) {
-//
-//	createGemInteworkingTp := "0012440A010A80010100058000000000" +
-//		"01000000000000000000000000000000" +
-//		"000000000000000000000028"
-//
-//	data, err := stringToPacket(createGemInteworkingTp)
-//	assert.NoError(t, err)
-//
-//	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-//	fmt.Println(packet)
-//
-//	customLayer := packet.Layer(LayerTypeOMCI)
-//	assert.NotNil(t, customLayer)
-//}
-
-func TestSet8021pMapperServiceProfile(t *testing.T) {
-	set8021pMapperServiceProfile := "0016480A008280004000800100000000" +
-		"00000000000000000000000000000000" +
-		"000000000000000000000028"
-
-	data, err := stringToPacket(set8021pMapperServiceProfile)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, packet)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x16))
-	assert.Equal(t, omciMsg.MessageType, SetRequestType)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeSetRequest)
-	assert.NotNil(t, msgLayer)
-
-	setRequest, ok2 := msgLayer.(*SetRequest)
-	assert.True(t, ok2)
-	assert.Equal(t, setRequest.EntityClass, Ieee8021PMapperServiceProfileClassID)
-	assert.Equal(t, setRequest.EntityInstance, uint16(0x8000))
-
-	attributes := setRequest.Attributes
-	assert.NotNil(t, attributes)
-	assert.Equal(t, len(attributes), 2)
-
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err = gopacket.SerializeLayers(buffer, options, omciMsg, setRequest)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(set8021pMapperServiceProfile), reconstituted)
-}
-
-// TODO: Uncomment as encode/decode supported
-//func TestCreateMacBridgePortConfigurationData(t *testing.T) {
-//
-//	createMacBridgePortConfigurationData := "001A440A002F21010201020380000000" +
-//		"00000000000000000000000000000000" +
-//		"000000000000000000000028"
-//
-//	data, err := stringToPacket(createMacBridgePortConfigurationData)
-//	assert.NoError(t, err)
-//
-//	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-//	fmt.Println(packet)
-//
-//	customLayer := packet.Layer(LayerTypeOMCI)
-//	assert.NotNil(t, customLayer)
-//}
-//
-//func TestCreateVlanTaggingFilterData(t *testing.T) {
-//
-//	createVlanTaggingFilterData := "001F440A005421010400000000000000" +
-//		"00000000000000000000000000000000" +
-//		"100100000000000000000028"
-//
-//	data, err := stringToPacket(createVlanTaggingFilterData)
-//	assert.NoError(t, err)
-//
-//	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-//	fmt.Println(packet)
-//
-//	customLayer := packet.Layer(LayerTypeOMCI)
-//	assert.NotNil(t, customLayer)
-//}
-//
-//func TestCreateExtendedVlanTaggingOperationConfigurationData(t *testing.T) {
-//
-//	createExtendedVlanTaggingOperationConfigurationData := "0023440A00AB02020A04010000000000" +
-//		"00000000000000000000000000000000" +
-//		"000000000000000000000028"
-//
-//	data, err := stringToPacket(createExtendedVlanTaggingOperationConfigurationData)
-//	assert.NoError(t, err)
-//
-//	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-//	fmt.Println(packet)
-//}
-//
-//func TestSetExtendedVlanTagging_operationConfigurationData(t *testing.T) {
-//
-//	setExtendedVlanTaggingOperationConfigurationData := "0024480A00AB02023800810081000000" +
-//		"00000000000000000000000000000000" +
-//		"000000000000000000000028"
-//
-//	data, err := stringToPacket(setExtendedVlanTaggingOperationConfigurationData)
-//	assert.NoError(t, err)
-//
-//	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-//	fmt.Println(packet)
-//
-//	customLayer := packet.Layer(LayerTypeOMCI)
-//	assert.NotNil(t, customLayer)
-//}
-//
-//func TestSetExtendedVlanTagging1(t *testing.T) {
-//
-//	setExtendedVlanTagging1 := "0025480A00AB02020400f00000008200" +
-//		"5000402f000000082004000000000000" +
-//		"000000000000000000000028"
-//
-//	data, err := stringToPacket(setExtendedVlanTagging1)
-//	assert.NoError(t, err)
-//
-//	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-//	fmt.Println(packet)
-//
-//	customLayer := packet.Layer(LayerTypeOMCI)
-//	assert.NotNil(t, customLayer)
-//}
-//
-//func TestSetExtendedVlanTagging2(t *testing.T) {
-//
-//	setExtendedVlanTagging2 := "0026480A00AB02020400F00000008200" +
-//		"d000402f00000008200c000000000000" +
-//		"000000000000000000000028"
-//
-//	data, err := stringToPacket(setExtendedVlanTagging2)
-//	assert.NoError(t, err)
-//
-//	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-//	fmt.Println(packet)
-//
-//	customLayer := packet.Layer(LayerTypeOMCI)
-//	assert.NotNil(t, customLayer)
-//}
-//
-//func TestCreateMacBridgePortConfigurationData2(t *testing.T) {
-//
-//	createMacBridgePortConfigurationData2 := "0029440A002F02010201010b04010000" +
-//		"00000000000000000000000000000000" +
-//		"000000000000000000000028"
-//
-//	data, err := stringToPacket(createMacBridgePortConfigurationData2)
-//	assert.NoError(t, err)
-//
-//	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-//	fmt.Println(packet)
-//
-//	customLayer := packet.Layer(LayerTypeOMCI)
-//	assert.NotNil(t, customLayer)
-//}
-
-func TestMibUpload(t *testing.T) {
-	mibUpload := "00304D0A000200000000000000000000" +
-		"00000000000000000000000000000000" +
-		"000000000000000000000028"
-
-	data, err := stringToPacket(mibUpload)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, packet)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x30))
-	assert.Equal(t, omciMsg.MessageType, MibUploadRequestType)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeMibUploadRequest)
-	assert.NotNil(t, msgLayer)
-
-	uploadRequest, ok2 := msgLayer.(*MibUploadRequest)
-	assert.True(t, ok2)
-	assert.Equal(t, uploadRequest.EntityClass, OnuDataClassID)
-	assert.Equal(t, uploadRequest.EntityInstance, uint16(0))
-
-	// Test serialization back to former string
-	var options gopacket.SerializeOptions
-	options.FixLengths = true
-
-	buffer := gopacket.NewSerializeBuffer()
-	err = gopacket.SerializeLayers(buffer, options, omciMsg, uploadRequest)
-	assert.NoError(t, err)
-
-	outgoingPacket := buffer.Bytes()
-	reconstituted := packetToString(outgoingPacket)
-	assert.Equal(t, strings.ToLower(mibUpload), reconstituted)
-}
-
-// TODO: Uncomment as encode/decode supported
-//func TestEnhSecurityAvc(t *testing.T) {
-//
-//	enhSecurityAvc := "0000110a014c0000008000202020202020202020202020202020202020202020" +
-//		"2020202020202020000000280be43cf4"
-//
-//	data, err := stringToPacket(enhSecurityAvc)
-//	assert.NoError(t, err)
-//
-//	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-//	fmt.Println(packet)
-//
-//	customLayer := packet.Layer(LayerTypeOMCI)
-//	assert.NotNil(t, customLayer)
-//}
-
-//func TestAlarmMessage(t *testing.T) {
-//	alarmMessage := "0000100a00050101000000000000000000000000000000000000000000000000" +
-//		"0000000220000000000000280be43cf4"
-//
-//	data, err := stringToPacket(alarmMessage)
-//	assert.NoError(t, err)
-//
-//	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-//	assert.NotNil(t, packet)
-//
-//	omciLayer := packet.Layer(LayerTypeOMCI)
-//	assert.NotNil(t, packet)
-//
-//	omciMsg, ok := omciLayer.(*OMCI)
-//	assert.True(t, ok)
-//	assert.Equal(t, omciMsg.TransactionID, uint16(0))
-//	assert.Equal(t, omciMsg.MessageType, byte(AlarmNotification))
-//	assert.Equal(t, omciMsg.Length, uint16(40))
-//
-//	msgLayer := packet.Layer(LayerTypeAlarmNotification)
-//	assert.Nil(t, msgLayer)		// TODO: Fix decode
-//
-//	//assert.NotNil(t, msgLayer)
-//	//
-//	//alarmNotification, ok2 := msgLayer.(*AlarmNotificationMsg)
-//	//assert.True(t, ok2)
-//	//// TODO: Repace with actual entity class
-//	//assert.Equal(t, alarmNotification.EntityClass, uint16(0x0005))
-//	//assert.Equal(t, alarmNotification.EntityInstance, uint16(0x101))
-//	// TODO: Decode alarm bits
-//
-//	// TODO: Serialize frame and test with original
-//}
-
-func TestOnuRebootRequest(t *testing.T) {
-	onuRebootRequest := "0016590a01000000000000000000000000000" +
-		"0000000000000000000000000000000000000" +
-		"00000000000028"
-
-	data, err := stringToPacket(onuRebootRequest)
-	assert.NoError(t, err)
-
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, packet)
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(0x16))
-	assert.Equal(t, omciMsg.MessageType, RebootRequestType)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	msgLayer := packet.Layer(LayerTypeRebootRequest)
-	assert.NotNil(t, msgLayer) // TODO: Fix decode
-
-	//assert.NotNil(t, msgLayer)
-	//
-	//rebootRequest, ok2 := msgLayer.(*RebootRequest)
-	//assert.True(t, ok2)
-	//assert.Equal(t, rebootRequest.EntityClass, OnuDataClassID)
-	//assert.Equal(t, rebootRequest.EntityInstance, uint16(0x8000))
-
-	// TODO: Test Decoded flags
-
-	// TODO: Serialize frame and test with original
-}
-
-func TestMibUploadNextSequence(t *testing.T) {
-	mibUploadNextSequence := [...]string{
-		"00032e0a00020000000200008000000000000000000000000000000000000000000000000000000000000028",
-		"00042e0a0002000000050101f0002f2f05202020202020202020202020202020202020202000000000000028",
-		"00052e0a00020000000501010f80202020202020202020202020202020202020202000000000000000000028",
-		"00062e0a0002000000050104f000303001202020202020202020202020202020202020202000000000000028",
-		"00072e0a00020000000501040f80202020202020202020202020202020202020202000000000000000000028",
-		"00082e0a0002000000050180f000f8f801202020202020202020202020202020202020202000000000000028",
-		"00092e0a00020000000501800f80202020202020202020202020202020202020202000000000000000000028",
-		"000a2e0a0002000000060101f0002f054252434d12345678000000000000000000000000000c000000000028",
-		"000b2e0a00020000000601010f004252434d0000000000000000000000000000000000000000000000000028",
-		"000c2e0a000200000006010100f8202020202020202020202020202020202020202000000000000000000028",
-		"000d2e0a00020000000601010004000000000000000000000000000000000000000000000000000000000028",
-		"000e2e0a0002000000060104f00030014252434d12345678000000000000000000000000000c000000000028",
-		"000f2e0a00020000000601040f004252434d0000000000000000000000000000000000000000000000000028",
-		"00102e0a000200000006010400f8202020202020202020202020202020202020202000000800000000000028",
-		"00112e0a00020000000601040004000000000000000000000000000000000000000000000000000000000028",
-		"00122e0a0002000000060180f000f8014252434d12345678000000000000000000000000000c000000000028",
-		"00132e0a00020000000601800f004252434d0000000000000000000000000000000000000000000000000028",
-		"00142e0a000200000006018000f8202020202020202020202020202020202020202000084040000000000028",
-		"00152e0a00020000000601800004000000000000000000000000000000000000000000000000000000000028",
-		"00162e0a0002000000070000f0003530323247574f3236363230303301010100000000000000000000000028",
-		"00172e0a0002000000070001f0003530323247574f3236363230303300000100000000000000000000000028",
-		"00182e0a0002000000830000c000202020202020202020202020202020202020202020202020000000000028",
-		"00192e0a00020000008300002000202020202020202020202020202000000000000000000000000000000028",
-		"001a2e0a00020000008300001000000000000000000000000000000000000000000000000000000000000028",
-		"001b2e0a0002000000850000ffe0000000000000000000000000000000000000000000000000000000000028",
-		"001c2e0a0002000000860001c00000001018aaaa000000000000000000000000000000000000000000000028",
-		"001d2e0a00020000008600012000000000000000000000000000000000000000000000000000000000000028",
-		"001e2e0a00020000008600011f80000000000000000000000000000000000000000000000000000000000028",
-		"001f2e0a00020000008600010078000000000000000000000000000000000000000000000000000000000028",
-		"00202e0a00020000008600010004000000000000000000000000000000000000000000000000000000000028",
-		"00212e0a00020000008600010002000000000000000000000000000000000000000000000000000000000028",
-		"00222e0a0002000001000000e0004252434d00000000000000000000000000004252434d1234567800000028",
-		"00232e0a00020000010000001f80000000000000000000000000000000000000000000000000000000000028",
-		"00242e0a00020000010000000040000000000000000000000000000000000000000000000000000000000028",
-		"00252e0a00020000010000000038000000000000000000000000000003000000000000000000000000000028",
-		"00262e0a0002000001010000f80042564d344b3030425241303931352d3030383300b3000001010000000028",
-		"00272e0a000200000101000007f8000000010020027c85630016000030000000000000000000000000000028",
-		"00282e0a0002000001068000e00000ff01010000000000000000000000000000000000000000000000000028",
-		"00292e0a0002000001068001e00000ff01010000000000000000000000000000000000000000000000000028",
-		"002a2e0a0002000001068002e00000ff01010000000000000000000000000000000000000000000000000028",
-		"002b2e0a0002000001068003e00000ff01010000000000000000000000000000000000000000000000000028",
-		"002c2e0a0002000001068004e00000ff01010000000000000000000000000000000000000000000000000028",
-		"002d2e0a0002000001068005e00000ff01010000000000000000000000000000000000000000000000000028",
-		"002e2e0a0002000001068006e00000ff01010000000000000000000000000000000000000000000000000028",
-		"002f2e0a0002000001068007e00000ff01010000000000000000000000000000000000000000000000000028",
-		"00302e0a0002000001078001ffff01000800300000050900000000ffff000000008181000000000000000028",
-		"00312e0a0002000001080401f000000000000401000000000000000000000000000000000000000000000028",
-		"00322e0a0002000001150401fff0000080008000000000040100000000010000000000000000000000000028",
-		"00332e0a0002000001150401000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00342e0a0002000001150402fff0000080008000000000040100010000010000000000000000000000000028",
-		"00352e0a0002000001150402000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00362e0a0002000001150403fff0000080008000000000040100020000010000000000000000000000000028",
-		"00372e0a0002000001150403000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00382e0a0002000001150404fff0000080008000000000040100030000010000000000000000000000000028",
-		"00392e0a0002000001150404000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"003a2e0a0002000001150405fff0000080008000000000040100040000010000000000000000000000000028",
-		"003b2e0a0002000001150405000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"003c2e0a0002000001150406fff0000080008000000000040100050000010000000000000000000000000028",
-		"003d2e0a0002000001150406000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"003e2e0a0002000001150407fff0000080008000000000040100060000010000000000000000000000000028",
-		"003f2e0a0002000001150407000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00402e0a0002000001150408fff0000080008000000000040100070000010000000000000000000000000028",
-		"00412e0a0002000001150408000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00422e0a0002000001158000fff0000100010000000000800000000000010000000000000000000000000028",
-		"00432e0a0002000001158000000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00442e0a0002000001158001fff0000100010000000000800000010000010000000000000000000000000028",
-		"00452e0a0002000001158001000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00462e0a0002000001158002fff0000100010000000000800000020000010000000000000000000000000028",
-		"00472e0a0002000001158002000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00482e0a0002000001158003fff0000100010000000000800000030000010000000000000000000000000028",
-		"00492e0a0002000001158003000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"004a2e0a0002000001158004fff0000100010000000000800000040000010000000000000000000000000028",
-		"004b2e0a0002000001158004000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"004c2e0a0002000001158005fff0000100010000000000800000050000010000000000000000000000000028",
-		"004d2e0a0002000001158005000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"004e2e0a0002000001158006fff0000100010000000000800000060000010000000000000000000000000028",
-		"004f2e0a0002000001158006000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00502e0a0002000001158007fff0000100010000000000800000070000010000000000000000000000000028",
-		"00512e0a0002000001158007000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00522e0a0002000001158008fff0000100010000000000800100000000010000000000000000000000000028",
-		"00532e0a0002000001158008000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00542e0a0002000001158009fff0000100010000000000800100010000010000000000000000000000000028",
-		"00552e0a0002000001158009000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00562e0a000200000115800afff0000100010000000000800100020000010000000000000000000000000028",
-		"00572e0a000200000115800a000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00582e0a000200000115800bfff0000100010000000000800100030000010000000000000000000000000028",
-		"00592e0a000200000115800b000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"005a2e0a000200000115800cfff0000100010000000000800100040000010000000000000000000000000028",
-		"005b2e0a000200000115800c000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"005c2e0a000200000115800dfff0000100010000000000800100050000010000000000000000000000000028",
-		"005d2e0a000200000115800d000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"005e2e0a000200000115800efff0000100010000000000800100060000010000000000000000000000000028",
-		"005f2e0a000200000115800e000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00602e0a000200000115800ffff0000100010000000000800100070000010000000000000000000000000028",
-		"00612e0a000200000115800f000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00622e0a0002000001158010fff0000100010000000000800200000000010000000000000000000000000028",
-		"00632e0a0002000001158010000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00642e0a0002000001158011fff0000100010000000000800200010000010000000000000000000000000028",
-		"00652e0a0002000001158011000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00662e0a0002000001158012fff0000100010000000000800200020000010000000000000000000000000028",
-		"00672e0a0002000001158012000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00682e0a0002000001158013fff0000100010000000000800200030000010000000000000000000000000028",
-		"00692e0a0002000001158013000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"006a2e0a0002000001158014fff0000100010000000000800200040000010000000000000000000000000028",
-		"006b2e0a0002000001158014000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"006c2e0a0002000001158015fff0000100010000000000800200050000010000000000000000000000000028",
-		"006d2e0a0002000001158015000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"006e2e0a0002000001158016fff0000100010000000000800200060000010000000000000000000000000028",
-		"006f2e0a0002000001158016000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00702e0a0002000001158017fff0000100010000000000800200070000010000000000000000000000000028",
-		"00712e0a0002000001158017000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00722e0a0002000001158018fff0000100010000000000800300000000010000000000000000000000000028",
-		"00732e0a0002000001158018000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00742e0a0002000001158019fff0000100010000000000800300010000010000000000000000000000000028",
-		"00752e0a0002000001158019000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00762e0a000200000115801afff0000100010000000000800300020000010000000000000000000000000028",
-		"00772e0a000200000115801a000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00782e0a000200000115801bfff0000100010000000000800300030000010000000000000000000000000028",
-		"00792e0a000200000115801b000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"007a2e0a000200000115801cfff0000100010000000000800300040000010000000000000000000000000028",
-		"007b2e0a000200000115801c000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"007c2e0a000200000115801dfff0000100010000000000800300050000010000000000000000000000000028",
-		"007d2e0a000200000115801d000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"007e2e0a000200000115801efff0000100010000000000800300060000010000000000000000000000000028",
-		"007f2e0a000200000115801e000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00802e0a000200000115801ffff0000100010000000000800300070000010000000000000000000000000028",
-		"00812e0a000200000115801f000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00822e0a0002000001158020fff0000100010000000000800400000000010000000000000000000000000028",
-		"00832e0a0002000001158020000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00842e0a0002000001158021fff0000100010000000000800400010000010000000000000000000000000028",
-		"00852e0a0002000001158021000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00862e0a0002000001158022fff0000100010000000000800400020000010000000000000000000000000028",
-		"00872e0a0002000001158022000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00882e0a0002000001158023fff0000100010000000000800400030000010000000000000000000000000028",
-		"00892e0a0002000001158023000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"008a2e0a0002000001158024fff0000100010000000000800400040000010000000000000000000000000028",
-		"008b2e0a0002000001158024000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"008c2e0a0002000001158025fff0000100010000000000800400050000010000000000000000000000000028",
-		"008d2e0a0002000001158025000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"008e2e0a0002000001158026fff0000100010000000000800400060000010000000000000000000000000028",
-		"008f2e0a0002000001158026000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00902e0a0002000001158027fff0000100010000000000800400070000010000000000000000000000000028",
-		"00912e0a0002000001158027000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00922e0a0002000001158028fff0000100010000000000800500000000010000000000000000000000000028",
-		"00932e0a0002000001158028000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00942e0a0002000001158029fff0000100010000000000800500010000010000000000000000000000000028",
-		"00952e0a0002000001158029000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00962e0a000200000115802afff0000100010000000000800500020000010000000000000000000000000028",
-		"00972e0a000200000115802a000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00982e0a000200000115802bfff0000100010000000000800500030000010000000000000000000000000028",
-		"00992e0a000200000115802b000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"009a2e0a000200000115802cfff0000100010000000000800500040000010000000000000000000000000028",
-		"009b2e0a000200000115802c000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"009c2e0a000200000115802dfff0000100010000000000800500050000010000000000000000000000000028",
-		"009d2e0a000200000115802d000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"009e2e0a000200000115802efff0000100010000000000800500060000010000000000000000000000000028",
-		"009f2e0a000200000115802e000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00a02e0a000200000115802ffff0000100010000000000800500070000010000000000000000000000000028",
-		"00a12e0a000200000115802f000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00a22e0a0002000001158030fff0000100010000000000800600000000010000000000000000000000000028",
-		"00a32e0a0002000001158030000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00a42e0a0002000001158031fff0000100010000000000800600010000010000000000000000000000000028",
-		"00a52e0a0002000001158031000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00a62e0a0002000001158032fff0000100010000000000800600020000010000000000000000000000000028",
-		"00a72e0a0002000001158032000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00a82e0a0002000001158033fff0000100010000000000800600030000010000000000000000000000000028",
-		"00a92e0a0002000001158033000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00aa2e0a0002000001158034fff0000100010000000000800600040000010000000000000000000000000028",
-		"00ab2e0a0002000001158034000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00ac2e0a0002000001158035fff0000100010000000000800600050000010000000000000000000000000028",
-		"00ad2e0a0002000001158035000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00ae2e0a0002000001158036fff0000100010000000000800600060000010000000000000000000000000028",
-		"00af2e0a0002000001158036000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00b02e0a0002000001158037fff0000100010000000000800600070000010000000000000000000000000028",
-		"00b12e0a0002000001158037000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00b22e0a0002000001158038fff0000100010000000000800700000000010000000000000000000000000028",
-		"00b32e0a0002000001158038000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00b42e0a0002000001158039fff0000100010000000000800700010000010000000000000000000000000028",
-		"00b52e0a0002000001158039000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00b62e0a000200000115803afff0000100010000000000800700020000010000000000000000000000000028",
-		"00b72e0a000200000115803a000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00b82e0a000200000115803bfff0000100010000000000800700030000010000000000000000000000000028",
-		"00b92e0a000200000115803b000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00ba2e0a000200000115803cfff0000100010000000000800700040000010000000000000000000000000028",
-		"00bb2e0a000200000115803c000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00bc2e0a000200000115803dfff0000100010000000000800700050000010000000000000000000000000028",
-		"00bd2e0a000200000115803d000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00be2e0a000200000115803efff0000100010000000000800700060000010000000000000000000000000028",
-		"00bf2e0a000200000115803e000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00c02e0a000200000115803ffff0000100010000000000800700070000010000000000000000000000000028",
-		"00c12e0a000200000115803f000f0200020002000200ffff0900000000000000000000000000000000000028",
-		"00c22e0a0002000001168000f000800000000200000000000000000000000000000000000000000000000028",
-		"00c32e0a0002000001168001f000800000000200000000000000000000000000000000000000000000000028",
-		"00c42e0a0002000001168002f000800000000200000000000000000000000000000000000000000000000028",
-		"00c52e0a0002000001168003f000800000000200000000000000000000000000000000000000000000000028",
-		"00c62e0a0002000001168004f000800000000200000000000000000000000000000000000000000000000028",
-		"00c72e0a0002000001168005f000800000000200000000000000000000000000000000000000000000000028",
-		"00c82e0a0002000001168006f000800000000200000000000000000000000000000000000000000000000028",
-		"00c92e0a0002000001168007f000800000000200000000000000000000000000000000000000000000000028",
-		"00ca2e0a0002000001168008f000800100000200000000000000000000000000000000000000000000000028",
-		"00cb2e0a0002000001168009f000800100000200000000000000000000000000000000000000000000000028",
-		"00cc2e0a000200000116800af000800100000200000000000000000000000000000000000000000000000028",
-		"00cd2e0a000200000116800bf000800100000200000000000000000000000000000000000000000000000028",
-		"00ce2e0a000200000116800cf000800100000200000000000000000000000000000000000000000000000028",
-		"00cf2e0a000200000116800df000800100000200000000000000000000000000000000000000000000000028",
-		"00d02e0a000200000116800ef000800100000200000000000000000000000000000000000000000000000028",
-		"00d12e0a000200000116800ff000800100000200000000000000000000000000000000000000000000000028",
-		"00d22e0a0002000001168010f000800200000200000000000000000000000000000000000000000000000028",
-		"00d32e0a0002000001168011f000800200000200000000000000000000000000000000000000000000000028",
-		"00d42e0a0002000001168012f000800200000200000000000000000000000000000000000000000000000028",
-		"00d52e0a0002000001168013f000800200000200000000000000000000000000000000000000000000000028",
-		"00d62e0a0002000001168014f000800200000200000000000000000000000000000000000000000000000028",
-		"00d72e0a0002000001168015f000800200000200000000000000000000000000000000000000000000000028",
-		"00d82e0a0002000001168016f000800200000200000000000000000000000000000000000000000000000028",
-		"00d92e0a0002000001168017f000800200000200000000000000000000000000000000000000000000000028",
-		"00da2e0a0002000001168018f000800300000200000000000000000000000000000000000000000000000028",
-		"00db2e0a0002000001168019f000800300000200000000000000000000000000000000000000000000000028",
-		"00dc2e0a000200000116801af000800300000200000000000000000000000000000000000000000000000028",
-		"00dd2e0a000200000116801bf000800300000200000000000000000000000000000000000000000000000028",
-		"00de2e0a000200000116801cf000800300000200000000000000000000000000000000000000000000000028",
-		"00df2e0a000200000116801df000800300000200000000000000000000000000000000000000000000000028",
-		"00e02e0a000200000116801ef000800300000200000000000000000000000000000000000000000000000028",
-		"00e12e0a000200000116801ff000800300000200000000000000000000000000000000000000000000000028",
-		"00e22e0a0002000001168020f000800400000200000000000000000000000000000000000000000000000028",
-		"00e32e0a0002000001168021f000800400000200000000000000000000000000000000000000000000000028",
-		"00e42e0a0002000001168022f000800400000200000000000000000000000000000000000000000000000028",
-		"00e52e0a0002000001168023f000800400000200000000000000000000000000000000000000000000000028",
-		"00e62e0a0002000001168024f000800400000200000000000000000000000000000000000000000000000028",
-		"00e72e0a0002000001168025f000800400000200000000000000000000000000000000000000000000000028",
-		"00e82e0a0002000001168026f000800400000200000000000000000000000000000000000000000000000028",
-		"00e92e0a0002000001168027f000800400000200000000000000000000000000000000000000000000000028",
-		"00ea2e0a0002000001168028f000800500000200000000000000000000000000000000000000000000000028",
-		"00eb2e0a0002000001168029f000800500000200000000000000000000000000000000000000000000000028",
-		"00ec2e0a000200000116802af000800500000200000000000000000000000000000000000000000000000028",
-		"00ed2e0a000200000116802bf000800500000200000000000000000000000000000000000000000000000028",
-		"00ee2e0a000200000116802cf000800500000200000000000000000000000000000000000000000000000028",
-		"00ef2e0a000200000116802df000800500000200000000000000000000000000000000000000000000000028",
-		"00f02e0a000200000116802ef000800500000200000000000000000000000000000000000000000000000028",
-		"00f12e0a000200000116802ff000800500000200000000000000000000000000000000000000000000000028",
-		"00f22e0a0002000001168030f000800600000200000000000000000000000000000000000000000000000028",
-		"00f32e0a0002000001168031f000800600000200000000000000000000000000000000000000000000000028",
-		"00f42e0a0002000001168032f000800600000200000000000000000000000000000000000000000000000028",
-		"00f52e0a0002000001168033f000800600000200000000000000000000000000000000000000000000000028",
-		"00f62e0a0002000001168034f000800600000200000000000000000000000000000000000000000000000028",
-		"00f72e0a0002000001168035f000800600000200000000000000000000000000000000000000000000000028",
-		"00f82e0a0002000001168036f000800600000200000000000000000000000000000000000000000000000028",
-		"00f92e0a0002000001168037f000800600000200000000000000000000000000000000000000000000000028",
-		"00fa2e0a0002000001168038f000800700000200000000000000000000000000000000000000000000000028",
-		"00fb2e0a0002000001168039f000800700000200000000000000000000000000000000000000000000000028",
-		"00fc2e0a000200000116803af000800700000200000000000000000000000000000000000000000000000028",
-		"00fd2e0a000200000116803bf000800700000200000000000000000000000000000000000000000000000028",
-		"00fe2e0a000200000116803cf000800700000200000000000000000000000000000000000000000000000028",
-		"00ff2e0a000200000116803df000800700000200000000000000000000000000000000000000000000000028",
-		"01002e0a000200000116803ef000800700000200000000000000000000000000000000000000000000000028",
-		"01012e0a000200000116803ff000800700000200000000000000000000000000000000000000000000000028",
-		"01022e0a0002000001490401c000000000000000000000000000000000000000000000000000000000000028",
-		"01032e0a00020000014904012000000000000000000000000000000000000000000000000000000000000028",
-		"01042e0a00020000014904011800ffffffff0000000000000000000000000000000000000000000000000028",
-	}
-	firstTid := uint16(3)
-
-	for _, packetString := range mibUploadNextSequence {
-		data, err := stringToPacket(packetString)
+		data, err := stringToPacket(msg39)
 		assert.NoError(t, err)
 
 		packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
 		assert.NotNil(t, packet)
 
 		omciLayer := packet.Layer(LayerTypeOMCI)
+		assert.Nil(t, omciLayer)
+
+		badLayer := packet.Layer(gopacket.LayerTypeDecodeFailure)
+		assert.NotNil(t, badLayer)
+		truncated := packet.Metadata().Truncated
+		assert.True(t, truncated)
+
+		// Let length be optional size baseline size is fixed and we can recover from that
+		msg40 := fmt.Sprintf("%04x%02x0a000200000000000000000000000000000000000000000000000000000000000000000000",
+			uint16(tid), uint8(msgType))
+		data, err = stringToPacket(msg40)
+		assert.NoError(t, err)
+
+		packet = gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+		assert.NotNil(t, packet)
+
+		omciLayer = packet.Layer(LayerTypeOMCI)
 		assert.NotNil(t, omciLayer)
 
 		omciMsg, ok := omciLayer.(*OMCI)
 		assert.True(t, ok)
-		assert.Equal(t, omciMsg.TransactionID, firstTid)
-		assert.Equal(t, omciMsg.MessageType, MibUploadNextResponseType)
-		assert.Equal(t, omciMsg.Length, uint16(40))
-
-		msgLayer := packet.Layer(LayerTypeMibUploadNextResponse)
-		assert.NotNil(t, msgLayer)
-
-		uploadResponse, ok2 := msgLayer.(*MibUploadNextResponse)
-		assert.True(t, ok2)
-		assert.Equal(t, uploadResponse.EntityClass, OnuDataClassID)
-		assert.Equal(t, uploadResponse.EntityInstance, uint16(0))
-
-		// Test serialization back to former string
-		var options gopacket.SerializeOptions
-		options.FixLengths = true
-
-		buffer := gopacket.NewSerializeBuffer()
-		err = gopacket.SerializeLayers(buffer, options, omciMsg, uploadResponse)
-		assert.NoError(t, err)
-
-		outgoingPacket := buffer.Bytes()
-		reconstituted := packetToString(outgoingPacket)
-		assert.Equal(t, strings.ToLower(packetString), reconstituted)
-
-		// Advance TID
-		firstTid += 1
+		assert.Equal(t, uint16(40), omciMsg.Length)
 	}
 }
 
-//func TestMibUploadNextWithMIC(t *testing.T) {
-//	// Similar to previous, but with the MIC available for testing
-//	mibUploadNextSequence := [...]string{
-//		"00032e0a0002000000020000800000000000000000000000000000000000000000000000000000000000002828ce00e2",
-//		"00042e0a0002000000050101f0002f2f05202020202020202020202020202020202020202000000000000028d4eb4bdf",
-//		"00052e0a00020000000501010f802020202020202020202020202020202020202020000000000000000000282dbe4b44",
-//		"00062e0a0002000000050104f000303001202020202020202020202020202020202020202000000000000028ef1b035b",
-//	}
-//	firstTid := uint16(3)
-//
-//	for pktNumber, packetString := range mibUploadNextSequence {
-//		data, err := stringToPacket(packetString)
-//		assert.NoError(t, err)
-//
-//		packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-//		fmt.Printf("Packet: %v: %v", pktNumber, packet)
-//		assert.NotNil(t, packet)
-//
-//		omciLayer := packet.Layer(LayerTypeOMCI)
-//		assert.NotNil(t, omciLayer)
-//
-//		omciMsg, ok := omciLayer.(*OMCI)
-//		assert.True(t, ok)
-//		assert.Equal(t, omciMsg.TransactionID, firstTid)
-//		assert.Equal(t, omciMsg.MessageType, byte(MibUploadNext))
-//		assert.Equal(t, omciMsg.Length, uint16(40))
-//
-//		msgLayer := packet.Layer(LayerTypeMibUploadNextResponse)
-//		assert.NotNil(t, msgLayer)
-//
-//		uploadResponse, ok2 := msgLayer.(*MibUploadNextResponse)
-//		assert.True(t, ok2)
-//		assert.Equal(t, uploadResponse.EntityClass, OnuDataClassID)
-//		assert.Equal(t, uploadResponse.EntityInstance, uint16(0))
-//
-//		// Test serialization back to former string
-//		var options gopacket.SerializeOptions
-//		options.FixLengths = true
-//
-//		buffer := gopacket.NewSerializeBuffer()
-//		err = gopacket.SerializeLayers(buffer, options, omciMsg, uploadResponse)
-//		assert.NoError(t, err)
-//
-//		outgoingPacket := buffer.Bytes()
-//		reconstituted := packetToString(outgoingPacket)
-//		assert.Equal(t,  strings.ToLower(packetString), reconstituted)
-//
-//		// Advance TID
-//		firstTid += 1
-//	}
-//}
+func TestOmciHeaderExtendedShort(t *testing.T) {
+	// Smallest message possible is an Extended Set Delete request which
+	// is 10 octets.
 
-// TestUnsupportedG988ClassIDMibUploadNextResponse tests decoding of an Unknown class ID that is
-// in the range of IDs assigned for G.988 use
-func TestUnsupportedG988ClassIDMibUploadNextResponse(t *testing.T) {
-	// The unsupported G.988 class ID below is 37 (0x0025), which is marked in the G.988
-	// (11/2017) as 'Intentionally left blank).  The encoded frame is a Get-Next
-	// response with a single attribute 1 & 16 (0x8001) encoded.
-	//
-	tid := 3
-	cid := 0x25
-	eid := 1
-	mask := 0x8000
-	omci_hdr := "00032e0a"
-	msg_hdr := "00020000002500018000"
-	attr := "0102030405060708090A0B0C0D0E0F101112131415161718191A"
-	trailer := "0000002828ce00e2"
-	msg := omci_hdr + msg_hdr + attr + trailer
-	data, err := stringToPacket(msg)
-	assert.NoError(t, err)
+	//mibResetRequest := "0001 4F 0A 0002 0000 0000000000000000" +
+	//	"00000000000000000000000000000000" +
+	//	"000000000000000000000028"
 
-	// Decode packet (lazy this time)
-	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.Lazy)
-	assert.NotNil(t, packet)
-
-	// OMCI Layer Contents are the
-	//   - TCI          (2 bytes)
-	//   - Msg Type     (1 byte)
-	//   - Device Ident (1 byte)
-	//
-	// payload is remaining layers (less optional length and MIC)
-
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, packet)
-
-	contents := omciLayer.LayerContents()
-	payload := omciLayer.LayerPayload()
-	assert.NotNil(t, contents)
-	assert.NotNil(t, payload)
-	assert.Equal(t, len(omci_hdr)/2, len(contents))
-	assert.Equal(t, (len(msg_hdr)+len(attr))/2, len(payload))
-
-	omciMsg, ok := omciLayer.(*OMCI)
-	assert.True(t, ok)
-	assert.Equal(t, omciMsg.TransactionID, uint16(tid))
-	assert.Equal(t, omciMsg.MessageType, MibUploadNextResponseType)
-	assert.Equal(t, omciMsg.Length, uint16(40))
-
-	// Message Layer contents for a MIB upload next response are the
-	//    - ONU Data Class/Instance                   (4 bytes)
-	//    - Reported Managed Entity Class/Instance    (4 bytes)
-	//    - Attribute Mask                            (2 bytes)
-	//
-	// Message Layer payload for a MIB upload next response are the attributes
-	// and zero-padding (but not length & MIC)
-
-	msgLayer := packet.Layer(LayerTypeMibUploadNextResponse)
-	assert.NotNil(t, msgLayer)
-
-	contents = msgLayer.LayerContents()
-	payload = msgLayer.LayerPayload()
-	assert.NotNil(t, contents)
-	assert.NotNil(t, payload)
-	assert.Equal(t, len(msg_hdr)/2, len(contents))
-	assert.Equal(t, len(attr)/2, len(payload))
-
-	uploadResponse, ok2 := msgLayer.(*MibUploadNextResponse)
-	assert.True(t, ok2)
-	assert.NotNil(t, uploadResponse)
-	assert.Equal(t, uploadResponse.EntityClass, OnuDataClassID)
-	assert.Equal(t, uploadResponse.EntityInstance, uint16(0))
-	assert.Equal(t, uploadResponse.ReportedME.GetClassID(), ClassID(cid))
-	assert.Equal(t, uploadResponse.ReportedME.GetEntityID(), uint16(eid))
-	assert.Equal(t, uploadResponse.ReportedME.GetAttributeMask(), uint16(mask))
-
-	name := "UnknownAttr_1"
-	blobAttribute, err := uploadResponse.ReportedME.GetAttribute(name)
-
-	assert.Nil(t, err)
-	assert.NotNil(t, blobAttribute)
-
-	byteValue, ok3 := blobAttribute.([]uint8)
-	assert.True(t, ok3)
-	assert.NotNil(t, byteValue)
 }
 
-func TestUnsupportedG988ClassIDMibUploadNextResponseAttributes(t *testing.T) {
-	// Same as previous, but try different attribute mask combinations
-	tid := 3
-	cid := 0x25
-	eid := 1
+func TestBad2017_G_988(t *testing.T) {
+	// ITU-G.988 11/2017 has a bad set of class IDs that map the Ethernet 64-bit PM counter
+	// to class ID 426 when it should be 425.   Make sure that code-generation of the OMCI
+	// ME's does not let that bad value find it's way back into our library.
 
-	// There are a number of ranges for vendor ID use. List below picks one from
-	// each of those ranges
-	masks := []uint16{0x8001, 0x0000, 0x0001, 0x8000}
+	assert.Equal(t, ClassID(425), EthernetFrameExtendedPm64BitClassID)
 
-	trailer := "0000002828ce00e2"
-	attr := "0102030405060708090A0B0C0D0E0F101112131415161718191A"
+	instance, omciErr := NewEthernetFrameExtendedPm64Bit()
+	assert.NotNil(t, instance)
+	assert.NotNil(t, omciErr)
+	assert.Equal(t, omciErr.StatusCode(), Success)
+	assert.Equal(t, EthernetFrameExtendedPm64BitClassID, instance.GetClassID())
+}
 
-	for _, mask := range masks {
-		hdr := fmt.Sprintf("00032e0a0002000000250001%04x", mask)
-
-		msg := hdr + attr + trailer
-		data, err := stringToPacket(msg)
-		assert.NoError(t, err)
-
-		packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-		assert.NotNil(t, packet)
-
-		omciLayer := packet.Layer(LayerTypeOMCI)
-		assert.NotNil(t, packet)
-
-		omciMsg, ok := omciLayer.(*OMCI)
-		assert.True(t, ok)
-		assert.Equal(t, omciMsg.TransactionID, uint16(tid))
-		assert.Equal(t, omciMsg.MessageType, MibUploadNextResponseType)
-		assert.Equal(t, omciMsg.Length, uint16(40))
-
-		msgLayer := packet.Layer(LayerTypeMibUploadNextResponse)
-		assert.NotNil(t, msgLayer)
-
-		uploadResponse, ok2 := msgLayer.(*MibUploadNextResponse)
-		assert.True(t, ok2)
-		assert.NotNil(t, uploadResponse)
-		assert.Equal(t, uploadResponse.EntityClass, OnuDataClassID)
-		assert.Equal(t, uploadResponse.EntityInstance, uint16(0))
-		assert.Equal(t, uploadResponse.ReportedME.GetClassID(), ClassID(cid))
-		assert.Equal(t, uploadResponse.ReportedME.GetEntityID(), uint16(eid))
-		assert.Equal(t, uploadResponse.ReportedME.GetAttributeMask(), uint16(mask))
-
-		//name := "UnknownAttr_1"
-		//blobAttribute, err := uploadResponse.ReportedME.GetAttribute(name)
-		//
-		//assert.Nil(t, err)
-		//assert.NotNil(t, blobAttribute)
-		//
-		//byteValue, ok3 := blobAttribute.([]uint8)
-		//assert.True(t, ok3)
-		//assert.NotNil(t, byteValue)
+func TestBaselineBadLenSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID:    0x0211,
+		MessageType:      DeleteResponseType,
+		DeviceIdentifier: BaselineIdent,
+		Length:           39, // Must be 0 or 40
 	}
-}
-
-// TestUnsupportedVendorClassIDMibUploadNextResponse tests decoding of an Unknown class ID that is
-// in the range of IDs assigned for vendor assignment
-func TestUnsupportedVendorClassIDMibUploadNextResponse(t *testing.T) {
-	tid := 3
-	eid := 0
-	mask := 0x8000
-
-	// There are a number of ranges for vendor ID use. List below picks one from
-	// each of those ranges
-	classIDs := []uint16{250, 355, 65500}
-
-	hdr := "00032e0a00020000"
-	attr := "0102030405060708090A0B0C0D0E0F101112131415161718191A"
-	trailer := "0000002828ce00e2"
-
-	for _, cid := range classIDs {
-		cidToMask := fmt.Sprintf("%04x%04x%04x", cid, eid, mask)
-		msg := hdr + cidToMask + attr + trailer
-		data, err := stringToPacket(msg)
-		assert.NoError(t, err)
-
-		packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
-		assert.NotNil(t, packet)
-
-		omciLayer := packet.Layer(LayerTypeOMCI)
-		assert.NotNil(t, packet)
-
-		omciMsg, ok := omciLayer.(*OMCI)
-		assert.True(t, ok)
-		assert.Equal(t, omciMsg.TransactionID, uint16(tid))
-		assert.Equal(t, omciMsg.MessageType, MibUploadNextResponseType)
-		assert.Equal(t, omciMsg.Length, uint16(40))
-
-		msgLayer := packet.Layer(LayerTypeMibUploadNextResponse)
-		assert.NotNil(t, msgLayer)
-
-		uploadResponse, ok2 := msgLayer.(*MibUploadNextResponse)
-		assert.True(t, ok2)
-		assert.NotNil(t, uploadResponse)
-		assert.Equal(t, uploadResponse.EntityClass, OnuDataClassID)
-		assert.Equal(t, uploadResponse.EntityInstance, uint16(0))
-		assert.Equal(t, uploadResponse.ReportedME.GetClassID(), ClassID(cid))
-		assert.Equal(t, uploadResponse.ReportedME.GetEntityID(), uint16(eid))
-		assert.Equal(t, uploadResponse.ReportedME.GetAttributeMask(), uint16(mask))
-
-		name := "UnknownAttr_1"
-		blobAttribute, err := uploadResponse.ReportedME.GetAttribute(name)
-
-		assert.Nil(t, err)
-		assert.NotNil(t, blobAttribute)
-
-		byteValue, ok3 := blobAttribute.([]uint8)
-		assert.True(t, ok3)
-		assert.NotNil(t, byteValue)
-	}
-}
-
-func TestCreateMulticastOperationsProfileMe(t *testing.T) {
-	// Test various create request for this ME
-	meParams := ParamData{
-		EntityID: uint16(0x501),
-		Attributes: AttributeValueMap{
-			"IgmpVersion":               2,
-			"IgmpFunction":              0,
-			"ImmediateLeave":            0,
-			"USIgmpTci":                 0,
-			"Robustness":                2,
-			"QuerierIp":                 0,
-			"QueryInterval":             125,
-			"QuerierMaxResponseTime":    100,
-			"LastMemberResponseTime":    10,
-			"UnauthorizedJoinBehaviour": 0,
-			"USIgmpRate":                0,
-			"USIgmpTagCtrl":             0,
-			"DSIgmpMcastTci":            []byte{0, 0, 0},
+	request := &DeleteResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x202),
 		},
+		Result: Success,
 	}
-	meInstance, newErr := NewMulticastOperationsProfile(meParams)
-	assert.NotNil(t, meInstance)
-	assert.Equal(t, newErr.StatusCode(), Success)
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
 
-	tid := uint16(123)
-	frame, omciErr := GenFrame(meInstance, CreateRequestType, TransactionID(tid))
-	assert.NotNil(t, frame)
-	assert.NotZero(t, len(frame))
-	assert.Nil(t, omciErr)
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
 
-	///////////////////////////////////////////////////////////////////
-	// Now decode
-	packet := gopacket.NewPacket(frame, LayerTypeOMCI, gopacket.NoCopy)
-	assert.NotNil(t, packet)
+func TestBadIdentSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID:    0x0211,
+		MessageType:      DeleteResponseType,
+		DeviceIdentifier: DeviceIdent(1), // Default is Baseline (0xa), other is Extended (0xb)
+	}
+	request := &DeleteResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x202),
+		},
+		Result: Success,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
 
-	omciLayer := packet.Layer(LayerTypeOMCI)
-	assert.NotNil(t, omciLayer)
-
-	omciObj, omciOk := omciLayer.(*OMCI)
-	assert.NotNil(t, omciObj)
-	assert.True(t, omciOk)
-	assert.Equal(t, tid, omciObj.TransactionID)
-	assert.Equal(t, CreateRequestType, omciObj.MessageType)
-	assert.Equal(t, BaselineIdent, omciObj.DeviceIdentifier)
-
-	msgLayer := packet.Layer(LayerTypeCreateRequest)
-	assert.NotNil(t, msgLayer)
-
-	msgObj, msgOk := msgLayer.(*CreateRequest)
-	assert.NotNil(t, msgObj)
-	assert.True(t, msgOk)
-
-	assert.Equal(t, meInstance.GetClassID(), msgObj.EntityClass)
-	assert.Equal(t, meInstance.GetEntityID(), msgObj.EntityInstance)
-	//assert.Equal(t, meInstance.GetAttributeValueMap(), msgObj.Attributes)
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
 }
diff --git a/reboot.go b/reboot.go
new file mode 100644
index 0000000..f2983ca
--- /dev/null
+++ b/reboot.go
@@ -0,0 +1,239 @@
+/*
+ * 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"
+	"github.com/google/gopacket"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+type RebootRequest struct {
+	MeBasePacket
+	RebootCondition byte
+}
+
+func (omci *RebootRequest) String() string {
+	return fmt.Sprintf("%v, Reboot Condition: %v",
+		omci.MeBasePacket.String(), omci.RebootCondition)
+}
+
+// LayerType returns LayerTypeRebootRequest
+func (omci *RebootRequest) LayerType() gopacket.LayerType {
+	return LayerTypeRebootRequest
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *RebootRequest) CanDecode() gopacket.LayerClass {
+	return LayerTypeRebootRequest
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *RebootRequest) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6 + 1
+	} else {
+		hdrSize = 4 + 1
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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")
+	}
+	offset := hdrSize - 1
+	omci.RebootCondition = data[offset]
+	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)
+}
+
+func decodeRebootRequestExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &RebootRequest{}
+	omci.MsgLayerType = LayerTypeRebootRequest
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Reboot Request message
+func (omci *RebootRequest) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	} else {
+		offset = 0
+	}
+	bytes, err := b.AppendBytes(offset + 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))
+	}
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, 1)
+	}
+	bytes[offset] = 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)
+}
+
+// LayerType returns LayerTypeRebootResponse
+func (omci *RebootResponse) LayerType() gopacket.LayerType {
+	return LayerTypeRebootResponse
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *RebootResponse) CanDecode() gopacket.LayerClass {
+	return LayerTypeRebootResponse
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *RebootResponse) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6 + 1
+	} else {
+		hdrSize = 4 + 1
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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)
+	}
+	offset := hdrSize - 1
+	omci.Result = me.Results(data[offset])
+	return nil
+}
+
+func decodeRebootResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &RebootResponse{}
+	omci.MsgLayerType = LayerTypeRebootResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+func decodeRebootResponseExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &RebootResponse{}
+	omci.MsgLayerType = LayerTypeRebootResponse
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Reboot Response message
+func (omci *RebootResponse) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	} else {
+		offset = 0
+	}
+	bytes, err := b.AppendBytes(offset + 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)
+	}
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, 1)
+	}
+	bytes[offset] = byte(omci.Result)
+	return nil
+}
diff --git a/reboot_test.go b/reboot_test.go
new file mode 100644
index 0000000..295a396
--- /dev/null
+++ b/reboot_test.go
@@ -0,0 +1,372 @@
+/*
+ * 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_test
+
+import (
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/stretchr/testify/assert"
+	"strings"
+	"testing"
+)
+
+func TestRebootRequestDecode(t *testing.T) {
+	goodMessage := "0001590a01000000010000000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeRebootRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0001), omciMsg.TransactionID)
+	assert.Equal(t, RebootRequestType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeRebootRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*RebootRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeRebootRequest, request.LayerType())
+	assert.Equal(t, LayerTypeRebootRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, me.OnuGClassID, request.EntityClass)
+	assert.Equal(t, uint16(0), request.EntityInstance)
+	assert.Equal(t, uint8(1), request.RebootCondition)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestRebootRequestSerialize(t *testing.T) {
+	goodMessage := "0001590a01000000020000000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x0001,
+		MessageType:   RebootRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &RebootRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass: me.OnuGClassID,
+			// Default Instance ID is 0
+		},
+		RebootCondition: uint8(2),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestRebootRequestZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   RebootRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &RebootRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass: me.OnuGClassID,
+			// Default Instance ID is 0
+		},
+		RebootCondition: uint8(2),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestRebootResponseDecode(t *testing.T) {
+	goodMessage := "023c390a01000000000000000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeRebootResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x023c), omciMsg.TransactionID)
+	assert.Equal(t, RebootResponseType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeRebootResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*RebootResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeRebootResponse, response.LayerType())
+	assert.Equal(t, LayerTypeRebootResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, me.OnuGClassID, response.EntityClass)
+	assert.Equal(t, uint16(0), response.EntityInstance)
+	assert.Equal(t, me.Success, response.Result)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestRebootResponseSerialize(t *testing.T) {
+	goodMessage := "023c390a01000000060000000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x023c,
+		MessageType:   RebootResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &RebootResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuGClassID,
+			EntityInstance: uint16(0),
+		},
+		Result: me.DeviceBusy,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestRebootResponseZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   RebootResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &RebootResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuGClassID,
+			EntityInstance: uint16(0),
+		},
+		Result: me.DeviceBusy,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestExtendedRebootRequestDecode(t *testing.T) {
+	goodMessage := "0001590b01000000000101"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeRebootRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0001), omciMsg.TransactionID)
+	assert.Equal(t, RebootRequestType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(1), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeRebootRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*RebootRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeRebootRequest, request.LayerType())
+	assert.Equal(t, LayerTypeRebootRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, me.OnuGClassID, request.EntityClass)
+	assert.Equal(t, uint16(0), request.EntityInstance)
+	assert.Equal(t, uint8(1), request.RebootCondition)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedRebootRequestSerialize(t *testing.T) {
+	goodMessage := "0001590b01000000000102"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0001,
+		MessageType:      RebootRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &RebootRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass: me.OnuGClassID,
+			Extended:    true,
+		},
+		RebootCondition: uint8(2),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestExtendedRebootResponseDecode(t *testing.T) {
+	goodMessage := "023c390b01000000000100"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeRebootResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x023c), omciMsg.TransactionID)
+	assert.Equal(t, RebootResponseType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(1), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeRebootResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*RebootResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeRebootResponse, response.LayerType())
+	assert.Equal(t, LayerTypeRebootResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, me.OnuGClassID, response.EntityClass)
+	assert.Equal(t, uint16(0), response.EntityInstance)
+	assert.Equal(t, me.Success, response.Result)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedRebootResponseSerialize(t *testing.T) {
+	goodMessage := "023c390b01000000000106"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x023c,
+		MessageType:      RebootResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &RebootResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuGClassID,
+			EntityInstance: uint16(0),
+			Extended:       true,
+		},
+		Result: me.DeviceBusy,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestOnuRebootRequest(t *testing.T) {
+	onuRebootRequest := "0016590a01000000000000000000000000000" +
+		"0000000000000000000000000000000000000" +
+		"00000000000028"
+
+	data, err := stringToPacket(onuRebootRequest)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, packet)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, uint16(0x16), omciMsg.TransactionID)
+	assert.Equal(t, RebootRequestType, omciMsg.MessageType)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeRebootRequest)
+	assert.NotNil(t, msgLayer)
+}
diff --git a/set.go b/set.go
new file mode 100644
index 0000000..e3fdb3b
--- /dev/null
+++ b/set.go
@@ -0,0 +1,295 @@
+/*
+ * 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"
+	"github.com/google/gopacket"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+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)
+}
+
+// LayerType returns LayerTypeSetRequest
+func (omci *SetRequest) LayerType() gopacket.LayerType {
+	return LayerTypeSetRequest
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *SetRequest) CanDecode() gopacket.LayerClass {
+	return LayerTypeSetRequest
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *SetRequest) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6 + 2
+	} else {
+		hdrSize = 4 + 2
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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")
+	}
+	offset := hdrSize - 2
+	omci.AttributeMask = binary.BigEndian.Uint16(data[offset:])
+
+	// Attribute decode
+	omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask, data[hdrSize:], 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
+	}
+	return me.NewProcessingError("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)
+}
+
+func decodeSetRequestExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &SetRequest{}
+	omci.MsgLayerType = LayerTypeSetRequest
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Set Request message
+func (omci *SetRequest) SerializeTo(b gopacket.SerializeBuffer, _ 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)
+		}
+	}
+	var maskOffset int
+	var bytesAvailable int
+	if omci.Extended {
+		maskOffset = 2
+		bytesAvailable = MaxExtendedLength - 12 - 4
+	} else {
+		maskOffset = 0
+		bytesAvailable = MaxBaselineLength - 10 - 8
+	}
+	// Attribute serialization
+	attributeBuffer := gopacket.NewSerializeBuffer()
+	err, _ = meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask, attributeBuffer,
+		byte(SetRequestType), bytesAvailable, false)
+
+	bytes, err := b.AppendBytes(maskOffset + 2 + len(attributeBuffer.Bytes()))
+	if err != nil {
+		return err
+	}
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, uint16(len(attributeBuffer.Bytes())+2))
+	}
+	binary.BigEndian.PutUint16(bytes[maskOffset:], omci.AttributeMask)
+	copy(bytes[maskOffset+2:], attributeBuffer.Bytes())
+	return nil
+}
+
+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)
+}
+
+// LayerType returns LayerTypeSetResponse
+func (omci *SetResponse) LayerType() gopacket.LayerType {
+	return LayerTypeSetResponse
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *SetResponse) CanDecode() gopacket.LayerClass {
+	return LayerTypeSetResponse
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *SetResponse) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6 + 1 // Plus 4 more if result = 9
+	} else {
+		hdrSize = 4 + 5
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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")
+	}
+	offset := hdrSize - 5
+	omci.Result = me.Results(data[offset])
+
+	if omci.Result == me.AttributeFailure {
+		// Optional attribute masks (4 octets) is required
+		if len(data) < hdrSize+4 {
+			p.SetTruncated()
+			return errors.New("frame too small")
+		}
+		omci.UnsupportedAttributeMask = binary.BigEndian.Uint16(data[offset+1:])
+		omci.FailedAttributeMask = binary.BigEndian.Uint16(data[offset+3:])
+	}
+	return nil
+}
+
+func decodeSetResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &SetResponse{}
+	omci.MsgLayerType = LayerTypeSetResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+func decodeSetResponseExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &SetResponse{}
+	omci.MsgLayerType = LayerTypeSetResponse
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Set Response message
+func (omci *SetResponse) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	var offset, length int
+	if omci.Extended {
+		offset = 2
+		length = 1
+		if omci.Result == me.AttributeFailure {
+			length += 4
+		}
+	} else {
+		offset = 0
+		length = 5
+	}
+	bytes, err := b.AppendBytes(offset + length)
+	if err != nil {
+		return err
+	}
+
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, uint16(length))
+		bytes[offset] = byte(omci.Result)
+		if omci.Result == me.AttributeFailure {
+			binary.BigEndian.PutUint16(bytes[offset+1:], omci.UnsupportedAttributeMask)
+			binary.BigEndian.PutUint16(bytes[offset+3:], omci.FailedAttributeMask)
+		}
+	} else {
+		bytes[offset] = byte(omci.Result)
+		binary.BigEndian.PutUint16(bytes[offset+1:], omci.UnsupportedAttributeMask)
+		binary.BigEndian.PutUint16(bytes[offset+3:], omci.FailedAttributeMask)
+	}
+	return nil
+}
diff --git a/set_test.go b/set_test.go
new file mode 100644
index 0000000..7cc04ef
--- /dev/null
+++ b/set_test.go
@@ -0,0 +1,451 @@
+/*
+ * 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_test
+
+import (
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/stretchr/testify/assert"
+	"strings"
+	"testing"
+)
+
+func TestSetRequestDecode(t *testing.T) {
+	goodMessage := "0107480a01000000020000000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeSetRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0107), omciMsg.TransactionID)
+	assert.Equal(t, SetRequestType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeSetRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*SetRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeSetRequest, request.LayerType())
+	assert.Equal(t, LayerTypeSetRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestSetRequestSerialize(t *testing.T) {
+	goodMessage := "0107480a01000000020001000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x0107,
+		MessageType:   SetRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &SetRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuGClassID,
+			EntityInstance: uint16(0),
+		},
+		AttributeMask: uint16(0x200),
+		Attributes:    me.AttributeValueMap{"AdministrativeState": byte(1)},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestSetRequestZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   SetRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &SetRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuGClassID,
+			EntityInstance: uint16(0),
+		},
+		AttributeMask: uint16(0x200),
+		Attributes:    me.AttributeValueMap{"AdministrativeState": byte(1)},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestSetResponseDecode(t *testing.T) {
+	goodMessage := "0107280a01000000000000000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeSetResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0107), omciMsg.TransactionID)
+	assert.Equal(t, SetResponseType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeSetResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*SetResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeSetResponse, response.LayerType())
+	assert.Equal(t, LayerTypeSetResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestSetResponseSerialize(t *testing.T) {
+	goodMessage := "0107280a01000000000000000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x0107,
+		MessageType:   SetResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &SetResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuGClassID,
+			EntityInstance: uint16(0),
+		},
+		Result: me.Success,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+
+}
+
+func TestSetResponseZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   SetResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &SetResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuGClassID,
+			EntityInstance: uint16(0),
+		},
+		Result: me.Success,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+
+}
+
+func TestExtendedSetRequestDecode(t *testing.T) {
+	goodMessage := "0107480b010000000003020001"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeSetRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0107), omciMsg.TransactionID)
+	assert.Equal(t, SetRequestType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(3), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeSetRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*SetRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeSetRequest, request.LayerType())
+	assert.Equal(t, LayerTypeSetRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, uint16(0x0200), request.AttributeMask)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedSetRequestSerialize(t *testing.T) {
+	goodMessage := "0107480b010000000003020001"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0107,
+		MessageType:      SetRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &SetRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuGClassID,
+			EntityInstance: uint16(0),
+			Extended:       true,
+		},
+		AttributeMask: uint16(0x200),
+		Attributes:    me.AttributeValueMap{"AdministrativeState": byte(1)},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestExtendedSetResponseDecode(t *testing.T) {
+	goodMessage := "0107280b01000000000100"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+	// TODO: Also test result == 9 decode
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeSetResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0107), omciMsg.TransactionID)
+	assert.Equal(t, SetResponseType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(1), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeSetResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*SetResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeSetResponse, response.LayerType())
+	assert.Equal(t, LayerTypeSetResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, me.Success, response.Result)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedSetResponseSerialize(t *testing.T) {
+	goodMessage := "0107280b01000000000103"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0107,
+		MessageType:      SetResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &SetResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuGClassID,
+			EntityInstance: uint16(0),
+			Extended:       true,
+		},
+		Result: me.ParameterError,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+
+}
+
+func TestSetResponseTableFailedAttributesDecode(t *testing.T) {
+	// This is a SET Response with failed and unsupported attributes
+	// TODO:Implement (also implement for Extended message set)
+}
+
+func TestSetResponseTableFailedAttributesSerialize(t *testing.T) {
+	// This is a SET Response with failed and unsupported attributes
+	// TODO:Implement (also implement for Extended message set)
+}
+
+func TestSetTCont(t *testing.T) {
+	setTCont := "0003480A010680008000040000000000" +
+		"00000000000000000000000000000000" +
+		"000000000000000000000028"
+
+	data, err := stringToPacket(setTCont)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, packet)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, uint16(3), omciMsg.TransactionID)
+	assert.Equal(t, SetRequestType, omciMsg.MessageType)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeSetRequest)
+	assert.NotNil(t, msgLayer)
+
+	omciMsg2, ok2 := msgLayer.(*SetRequest)
+	assert.True(t, ok2)
+	assert.Equal(t, me.TContClassID, omciMsg2.EntityClass)
+	assert.Equal(t, uint16(0x8000), omciMsg2.EntityInstance)
+
+	attributes := omciMsg2.Attributes
+	assert.Equal(t, 2, len(attributes))
+
+	// Here 1 is the index in the attribute definition map of a TCONT that points
+	// to the AllocID attribute.
+	value, ok3 := attributes["AllocId"]
+	assert.True(t, ok3)
+	assert.Equal(t, value, uint16(1024))
+
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err = gopacket.SerializeLayers(buffer, options, omciMsg, omciMsg2)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(setTCont), reconstituted)
+}
+
+func TestSet8021pMapperServiceProfile(t *testing.T) {
+	set8021pMapperServiceProfile := "0016480A008280004000800100000000" +
+		"00000000000000000000000000000000" +
+		"000000000000000000000028"
+
+	data, err := stringToPacket(set8021pMapperServiceProfile)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, packet)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, uint16(0x16), omciMsg.TransactionID)
+	assert.Equal(t, SetRequestType, omciMsg.MessageType)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeSetRequest)
+	assert.NotNil(t, msgLayer)
+
+	setRequest, ok2 := msgLayer.(*SetRequest)
+	assert.True(t, ok2)
+	assert.Equal(t, me.Ieee8021PMapperServiceProfileClassID, setRequest.EntityClass)
+	assert.Equal(t, uint16(0x8000), setRequest.EntityInstance)
+
+	attributes := setRequest.Attributes
+	assert.NotNil(t, attributes)
+	assert.Equal(t, 2, len(attributes))
+
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err = gopacket.SerializeLayers(buffer, options, omciMsg, setRequest)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(set8021pMapperServiceProfile), reconstituted)
+}
diff --git a/settable.go b/settable.go
new file mode 100644
index 0000000..61ceafd
--- /dev/null
+++ b/settable.go
@@ -0,0 +1,302 @@
+/*
+ * 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"
+	"github.com/google/gopacket"
+	me "github.com/opencord/omci-lib-go/generated"
+	"math/bits"
+)
+
+type SetTableRequest struct {
+	MeBasePacket
+	AttributeMask uint16
+	// Attributes below should be a single attribute whose value is of type TableRows
+	Attributes me.AttributeValueMap
+}
+
+func (omci *SetTableRequest) String() string {
+	return fmt.Sprintf("%v", omci.MeBasePacket.String())
+}
+
+// LayerType returns LayerTypeSetTableRequest
+func (omci *SetTableRequest) LayerType() gopacket.LayerType {
+	return LayerTypeSetTableRequest
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *SetTableRequest) CanDecode() gopacket.LayerClass {
+	return LayerTypeSetTableRequest
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *SetTableRequest) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// DecodeFromBytes decodes the given bytes of a Set Table Request into this layer
+func (omci *SetTableRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Only supported in the Extended message set
+	if !omci.Extended {
+		return me.NewNotSupportedError("baseline message set not supported by SetTable Message-Type")
+	}
+	// Common ClassID/EntityID decode in msgBase
+	hdrSize := 6 + 2
+
+	if len(data) < hdrSize {
+		p.SetTruncated()
+		return errors.New("frame too small")
+	} // Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, 6+2)
+	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 SetTable
+	if !me.SupportsMsgType(meDefinition, me.SetTable) {
+		return me.NewProcessingError("managed entity does not support SetTable Message-Type")
+	}
+	offset := hdrSize - 2
+	omci.AttributeMask = binary.BigEndian.Uint16(data[offset:])
+
+	// Only a single attribute bit can be set
+	if bits.OnesCount16(omci.AttributeMask) != 1 {
+		return me.NewProcessingError("only a single attribute can be specified for the SetTable Message-Type")
+	}
+	// Attribute decode
+	omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask, data[hdrSize:], p, byte(SetTableRequestType))
+	if err != nil {
+		return err
+	}
+	// Validate that the selected attribute support write and is a table
+	for attrName := range omci.Attributes {
+		attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
+		if err != nil {
+			return err
+		}
+		if attr.Index != 0 && attr.Mask == omci.AttributeMask {
+			if !me.SupportsAttributeAccess(*attr, me.Write) {
+				msg := fmt.Sprintf("attribute '%v' does not support write access", attrName)
+				return me.NewProcessingError(msg)
+			}
+			if !attr.IsTableAttribute() {
+				msg := fmt.Sprintf("attribute '%v' must be a table attribute for a SetTable Message-Type", attrName)
+				return me.NewProcessingError(msg)
+			}
+			break
+		}
+	}
+	if eidDef, eidDefOK := meDefinition.GetAttributeDefinitions()[0]; eidDefOK {
+		omci.Attributes[eidDef.GetName()] = omci.EntityInstance
+		return nil
+	}
+	return me.NewProcessingError("All Managed Entities have an EntityID attribute")
+}
+
+func decodeSetTableRequest(data []byte, p gopacket.PacketBuilder) error {
+	return me.NewNotSupportedError("baseline message set not supported by SetTable Message-Type")
+}
+
+func decodeSetTableRequestExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &SetTableRequest{}
+	omci.MsgLayerType = LayerTypeSetTableRequest
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Set Table Message Type Request
+func (omci *SetTableRequest) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
+	// Only Extended message set is supported for this message type
+	if !omci.Extended {
+		return me.NewNotSupportedError("only Extended Message set support for the SetTable Message-Type")
+	}
+	// Basic (common) OMCI Header
+	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 SetTable
+	if !me.SupportsMsgType(meDefinition, me.SetTable) {
+		return me.NewProcessingError("managed entity does not support SetTable Message-Type")
+	}
+	// Only a single attribute bit can be set for this request
+	if bits.OnesCount16(omci.AttributeMask) != 1 {
+		return me.NewProcessingError("only a single attribute can be specified for the SetTable Message-Type")
+	}
+	// Find the attributes and make sure it supports a 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 && attr.Mask == omci.AttributeMask {
+			// Must be a table attribute and support writes
+			if !me.SupportsAttributeAccess(*attr, me.Write) {
+				msg := fmt.Sprintf("attribute '%v' does not support write access", attrName)
+				return me.NewProcessingError(msg)
+			}
+			if !attr.IsTableAttribute() {
+				msg := fmt.Sprintf("attribute '%v' must be a table attribute for a SetTable Message-Type", attrName)
+				return me.NewProcessingError(msg)
+			}
+			break
+		}
+	}
+	// Attribute serialization
+	maskOffset := 1
+	maskOffset = 2
+	bytesAvailable := MaxExtendedLength - 12 - 4
+	attributeBuffer := gopacket.NewSerializeBuffer()
+	if attrErr, _ := meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask, attributeBuffer,
+		byte(SetTableRequestType), bytesAvailable, false); attrErr != nil {
+		return attrErr
+	}
+	bytes, err := b.AppendBytes(maskOffset + 2 + len(attributeBuffer.Bytes()))
+	if err != nil {
+		return err
+	}
+	// Encode the length nd attribute mask
+	binary.BigEndian.PutUint16(bytes, uint16(len(attributeBuffer.Bytes())+2))
+	binary.BigEndian.PutUint16(bytes[maskOffset:], omci.AttributeMask)
+	copy(bytes[maskOffset+2:], attributeBuffer.Bytes())
+	return nil
+}
+
+type SetTableResponse struct {
+	MeBasePacket
+	Result me.Results
+}
+
+func (omci *SetTableResponse) String() string {
+	return fmt.Sprintf("%v", omci.MeBasePacket.String())
+}
+
+// LayerType returns LayerTypeSetTableResponse
+func (omci *SetTableResponse) LayerType() gopacket.LayerType {
+	return LayerTypeSetTableResponse
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *SetTableResponse) CanDecode() gopacket.LayerClass {
+	return LayerTypeSetTableResponse
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *SetTableResponse) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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, 6+1)
+	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 SetTable
+	if !me.SupportsMsgType(entity, me.SetTable) {
+		return me.NewProcessingError("managed entity does not support the SetTable Message-Type")
+	}
+	omci.Result = me.Results(data[6])
+	if omci.Result == 7 || omci.Result == 8 || omci.Result >= 9 {
+		msg := fmt.Sprintf("invalid SetTable results code: %v, must be 0..6, 9", omci.Result)
+		return errors.New(msg)
+	}
+	return nil
+}
+
+func decodeSetTableResponse(data []byte, p gopacket.PacketBuilder) error {
+	return me.NewNotSupportedError("baseline message set not supported by SetTable Message-Type")
+}
+
+func decodeSetTableResponseExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &SetTableResponse{}
+	omci.MsgLayerType = LayerTypeSetTableResponse
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Set Table Message Type Response
+func (omci *SetTableResponse) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header
+	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 SetTable
+	if !me.SupportsMsgType(entity, me.SetTable) {
+		return me.NewProcessingError("managed entity does not support the SetTable Message-Type")
+	}
+	offset := 2
+	length := 1
+	bytes, err := b.AppendBytes(offset + length)
+	if err != nil {
+		return err
+	}
+	if omci.Result == 7 || omci.Result == 8 || omci.Result >= 9 {
+		msg := fmt.Sprintf("invalid SetTable results code: %v, must be 0..6, 9", omci.Result)
+		return errors.New(msg)
+	}
+	// TODO: Section A.1.1 (page 505) of ITU-G.988-202003 specifies that:
+	//   When the result-reason code in a response message indicates an exception (i.e., its
+	//   value is not 0), the response message is permitted to include vendor-specific
+	//   additional information. The rules for additional error information are as follows.
+	//
+	//     1.	Additional error information is optional for the ONU to insert.
+	//     2.	Additional information may or may not be represented in textual form.
+	//     3.	The semantics of additional error information are specific to the ONU vendor.
+	//     4.	The ONU must not rely on the OLT being able to detect or interpret additional
+	//    		error information.
+	//     5.	Additional error information may occupy only padding bytes (baseline message set)
+	//    		or only uncommitted trailing bytes (extended message set).
+	//     6.	In get, get current data and get next responses, the attribute mask controls the
+	//    		padding definition.
+	//     7.	No additional error information is permitted in responses to start download and
+	//    		end download messages that are directed to multiple target MEs, as indicated by
+	//   		0xFFFF in the target ME identifier.
+	//
+	// TODO: Add this capability to all appropriate response serializations and validate for
+	//       decodes the information is available through the Payload() function of the message-type
+
+	binary.BigEndian.PutUint16(bytes, uint16(1))
+	bytes[offset] = byte(omci.Result)
+	return nil
+}
diff --git a/settable_test.go b/settable_test.go
new file mode 100644
index 0000000..c65eb7e
--- /dev/null
+++ b/settable_test.go
@@ -0,0 +1,770 @@
+/*
+ * 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_test
+
+import (
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/stretchr/testify/assert"
+	"strings"
+	"testing"
+)
+
+func TestSetTableRequestDecode(t *testing.T) {
+	// Single row
+	row := "F0000000" + "F0000000" + "00000000" + "00000000"
+	goodMessage := "01075d0b00AB123400120400"
+	data, err := stringToPacket(goodMessage + row)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeSetTableRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0107), omciMsg.TransactionID)
+	assert.Equal(t, SetTableRequestType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(2+16), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeSetTableRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*SetTableRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeSetTableRequest, request.LayerType())
+	assert.Equal(t, LayerTypeSetTableRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+
+	assert.Equal(t, me.ExtendedVlanTaggingOperationConfigurationDataClassID, request.EntityClass)
+	assert.Equal(t, uint16(0x1234), request.EntityInstance)
+	assert.Equal(t, uint16(0x0400), request.AttributeMask)
+
+	vlanTable, tblOk := request.Attributes["ReceivedFrameVlanTaggingOperationTable"]
+	assert.True(t, tblOk)
+	assert.NotNil(t, vlanTable)
+
+	rows, rowOk := vlanTable.(me.TableRows)
+	assert.True(t, rowOk)
+	assert.NotNil(t, rows)
+	assert.Equal(t, 1, rows.NumRows)
+	assert.Equal(t, 16*rows.NumRows, len(rows.Rows))
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestSetTableRequestDecodeZeroRows(t *testing.T) {
+	// No rows are okay
+	row := ""
+	goodMessage := "01075d0b00AB123400020400"
+	data, err := stringToPacket(goodMessage + row)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, uint16(2), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeSetTableRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*SetTableRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, me.ExtendedVlanTaggingOperationConfigurationDataClassID, request.EntityClass)
+	assert.Equal(t, uint16(0x1234), request.EntityInstance)
+	assert.Equal(t, uint16(0x0400), request.AttributeMask)
+
+	vlanTable, tblOk := request.Attributes["ReceivedFrameVlanTaggingOperationTable"]
+	assert.True(t, tblOk)
+	assert.NotNil(t, vlanTable)
+
+	rows, rowOk := vlanTable.(me.TableRows)
+	assert.True(t, rowOk)
+	assert.NotNil(t, rows)
+	assert.Equal(t, 0, rows.NumRows)
+	assert.Nil(t, rows.Rows)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestSetTableRequestDecodeMultipleRows(t *testing.T) {
+	// More than one row
+	row1 := "F0000000" + "F0000000" + "00000000" + "00000000"
+	row2 := "70000000" + "F0000000" + "00000000" + "00000000"
+	row3 := "70000000" + "70000000" + "00000000" + "00000000"
+	goodMessage := "01075d0b00AB123400320400"
+	data, err := stringToPacket(goodMessage + row1 + row2 + row3)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, uint16(2+(3*16)), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeSetTableRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*SetTableRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	vlanTable, tblOk := request.Attributes["ReceivedFrameVlanTaggingOperationTable"]
+	assert.True(t, tblOk)
+	assert.NotNil(t, vlanTable)
+
+	rows, rowOk := vlanTable.(me.TableRows)
+	assert.True(t, rowOk)
+	assert.NotNil(t, rows)
+	assert.Equal(t, 3, rows.NumRows)
+	assert.Equal(t, 16*rows.NumRows, len(rows.Rows))
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestSetTableRequestDecodeTruncatedRow(t *testing.T) {
+	// More than one row, but one is short
+	row1 := "F0000000" + "F0000000" + "00000000" + "00000000"
+	row2 := "70000000" + "F0000000" + "00000000" + "00000000"
+	row3 := "70000000" + "70000000" + "00000000" + "0000"
+	goodMessage := "01075d0b00ab123400300400"
+	data, err := stringToPacket(goodMessage + row1 + row2 + row3)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, uint16(48), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeSetTableRequest)
+	assert.Nil(t, msgLayer)
+
+	shortLayer := packet.Layer(gopacket.LayerTypeDecodeFailure)
+	assert.NotNil(t, shortLayer)
+	assert.True(t, packet.Metadata().Truncated)
+}
+
+func TestSetTableRequestDecodeOneAttributeOnly(t *testing.T) {
+	// Single row but also extra non-table row
+	row := "F0000000" + "F0000000" + "00000000" + "00000000"
+	goodMessage := "01075d0b00ab123400138400" + "00"
+	data, err := stringToPacket(goodMessage + row)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeSetTableRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0107), omciMsg.TransactionID)
+	assert.Equal(t, SetTableRequestType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(3+16), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeSetTableRequest)
+	assert.Nil(t, msgLayer)
+
+	badLayer := packet.Layer(gopacket.LayerTypeDecodeFailure)
+	assert.NotNil(t, badLayer)
+	assert.False(t, packet.Metadata().Truncated) // It was correct length, but not right
+
+	failure, ok3 := badLayer.(*gopacket.DecodeFailure)
+	assert.True(t, ok3)
+	assert.NotNil(t, failure)
+}
+
+func TestSetTableRequestDecodeTableAttributesOnly(t *testing.T) {
+
+	// Single row but also extra non-table row
+	goodMessage := "01075d0b00ab123400038000" + "00"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeSetTableRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0107), omciMsg.TransactionID)
+	assert.Equal(t, SetTableRequestType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(3), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeSetTableRequest)
+	assert.Nil(t, msgLayer)
+
+	badLayer := packet.Layer(gopacket.LayerTypeDecodeFailure)
+	assert.NotNil(t, badLayer)
+	assert.False(t, packet.Metadata().Truncated) // It was correct length, but not right
+
+	failure, ok3 := badLayer.(*gopacket.DecodeFailure)
+	assert.True(t, ok3)
+	assert.NotNil(t, failure)
+}
+
+func TestSetTableRequestDecodeMeNotSupported(t *testing.T) {
+
+	// Single row but also extra non-table row
+	goodMessage := "01075d0b0100000000031000" + "01"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeSetTableRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0107), omciMsg.TransactionID)
+	assert.Equal(t, SetTableRequestType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(3), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeSetTableRequest)
+	assert.Nil(t, msgLayer)
+
+	badLayer := packet.Layer(gopacket.LayerTypeDecodeFailure)
+	assert.NotNil(t, badLayer)
+	assert.False(t, packet.Metadata().Truncated) // It was correct length, but not right
+
+	failure, ok3 := badLayer.(*gopacket.DecodeFailure)
+	assert.True(t, ok3)
+	assert.NotNil(t, failure)
+}
+
+func TestSetTableRequestDecodeTableWritableOnly(t *testing.T) {
+
+	// Single row but also extra non-table row
+	goodMessage := "01075d0b00ab123400044000" + "0000"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeSetTableRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0107), omciMsg.TransactionID)
+	assert.Equal(t, SetTableRequestType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(4), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeSetTableRequest)
+	assert.Nil(t, msgLayer)
+
+	badLayer := packet.Layer(gopacket.LayerTypeDecodeFailure)
+	assert.NotNil(t, badLayer)
+	assert.False(t, packet.Metadata().Truncated) // It was correct length, but not right
+
+	failure, ok3 := badLayer.(*gopacket.DecodeFailure)
+	assert.True(t, ok3)
+	assert.NotNil(t, failure)
+}
+
+func TestSetTableRequestDecodeBaselineNotSupported(t *testing.T) {
+	// Single row
+	message := "01075d0a00AB1234001204000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(message)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, uint16(0x0107), omciMsg.TransactionID)
+	assert.Equal(t, SetTableRequestType, omciMsg.MessageType)
+
+	msgLayer := packet.Layer(LayerTypeSetTableRequest)
+	assert.Nil(t, msgLayer)
+
+	badLayer := packet.Layer(gopacket.LayerTypeDecodeFailure)
+	assert.NotNil(t, badLayer)
+	assert.False(t, packet.Metadata().Truncated)
+}
+
+func TestSetTableRequestSerialize(t *testing.T) {
+	// Single row
+	row := "F0000001" + "F0000002" + "00000003" + "00000004"
+	goodMessage := "01075d0b00AB123400120400" + row
+
+	rowData, rErr := stringToPacket(row)
+	assert.NoError(t, rErr)
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0107,
+		MessageType:      SetTableRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	tableRow := me.TableRows{
+		NumRows: 1,
+		Rows:    rowData,
+	}
+	request := &SetTableRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x1234),
+			Extended:       true,
+		},
+		AttributeMask: uint16(0x0400),
+		Attributes:    me.AttributeValueMap{"ReceivedFrameVlanTaggingOperationTable": tableRow},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestSetTableRequestZeroTICSerialize(t *testing.T) {
+	// Single row
+	row := "F0000001" + "F0000002" + "00000003" + "00000004"
+	rowData, rErr := stringToPacket(row)
+	assert.NoError(t, rErr)
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0,
+		MessageType:      SetTableRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	tableRow := me.TableRows{
+		NumRows: 1,
+		Rows:    rowData,
+	}
+	request := &SetTableRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x1234),
+			Extended:       true,
+		},
+		AttributeMask: uint16(0x0400),
+		Attributes:    me.AttributeValueMap{"ReceivedFrameVlanTaggingOperationTable": tableRow},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestSetTableRequestSerializeZeroRows(t *testing.T) {
+	// No rows is sort of dumb on a set but technically it is allowed
+	goodMessage := "01075d0b00AB123400020400"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0107,
+		MessageType:      SetTableRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	tableRow := me.TableRows{}
+	request := &SetTableRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x1234),
+			Extended:       true,
+		},
+		AttributeMask: uint16(0x0400),
+		Attributes:    me.AttributeValueMap{"ReceivedFrameVlanTaggingOperationTable": tableRow},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestSetTableRequestSerializeMultipleRows(t *testing.T) {
+	// More than one row
+	row1 := "F0000000" + "F0000000" + "00004000" + "0000000c"
+	row2 := "70000000" + "F0000000" + "00300000" + "0000000a"
+	row3 := "70000000" + "70000000" + "0005000b" + "0000000b"
+	goodMessage := "01075d0b00AB123400320400" + row1 + row2 + row3
+
+	rowData, rErr := stringToPacket(row1 + row2 + row3)
+	assert.NoError(t, rErr)
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0107,
+		MessageType:      SetTableRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	tableRow := me.TableRows{
+		NumRows: 3,
+		Rows:    rowData,
+	}
+	request := &SetTableRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x1234),
+			Extended:       true,
+		},
+		AttributeMask: uint16(0x0400),
+		Attributes:    me.AttributeValueMap{"ReceivedFrameVlanTaggingOperationTable": tableRow},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestSetTableRequestSerializeTruncatedRow(t *testing.T) {
+	// More than one row, but one is short
+	row1 := "F0000000" + "F0000000" + "00000000" + "00000000"
+	row2 := "70000000" + "F0000000" + "00000000" + "00000000"
+	row3 := "70000000" + "70000000" + "00000000" + "0000"
+
+	rowData, rErr := stringToPacket(row1 + row2 + row3)
+	assert.NoError(t, rErr)
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0107,
+		MessageType:      SetTableRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	tableRow := me.TableRows{
+		NumRows: 3,
+		Rows:    rowData,
+	}
+	request := &SetTableRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x1234),
+			Extended:       true,
+		},
+		AttributeMask: uint16(0x0400),
+		Attributes:    me.AttributeValueMap{"ReceivedFrameVlanTaggingOperationTable": tableRow},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestSetTableRequestSerializeOneAttributeOnly(t *testing.T) {
+	rowData, rErr := stringToPacket("F0000000" + "F0000000" + "00000000" + "00000000")
+	assert.NoError(t, rErr)
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0107,
+		MessageType:      SetTableRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	tableRow := me.TableRows{
+		NumRows: 1,
+		Rows:    rowData,
+	}
+	request := &SetTableRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x1234),
+			Extended:       true,
+		},
+		AttributeMask: uint16(0x8400),
+		Attributes: me.AttributeValueMap{
+			"ReceivedFrameVlanTaggingOperationTable": tableRow,
+			"AssociationType":                        byte(1),
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestSetTableRequestSerializeTableAttributesOnly(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID:    0x0107,
+		MessageType:      SetTableRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &SetTableRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x1234),
+			Extended:       true,
+		},
+		AttributeMask: uint16(0x8000),
+		Attributes: me.AttributeValueMap{
+			"AssociationType": byte(1),
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestSetTableRequestSerializeTableWritableOnly(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID:    0x0107,
+		MessageType:      SetTableRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &SetTableRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x1234),
+			Extended:       true,
+		},
+		AttributeMask: uint16(0x4000),
+		Attributes: me.AttributeValueMap{
+			"ReceivedFrameVlanTaggingOperationTableMaxSize": byte(1),
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestSetTableRequestSerializeBaselineNotSupported(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID:    0x0107,
+		MessageType:      SetTableRequestType,
+		DeviceIdentifier: BaselineIdent,
+	}
+	tableRow := me.TableRows{}
+	request := &SetTableRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x1234),
+			Extended:       false,
+		},
+		AttributeMask: uint16(0x0400),
+		Attributes:    me.AttributeValueMap{"ReceivedFrameVlanTaggingOperationTable": tableRow},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestSetTableRequestSerializeBaselineManageEntityNotSupported(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID:    0x0107,
+		MessageType:      SetTableRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &SetTableRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuGClassID,
+			EntityInstance: uint16(0x0),
+			Extended:       true,
+		},
+		AttributeMask: uint16(0x1000),
+		Attributes:    me.AttributeValueMap{"TrafficManagementOption": byte(1)},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestSetTableResponseDecode(t *testing.T) {
+	goodMessage := "01073d0b00ab1234000101"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeSetTableResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0107), omciMsg.TransactionID)
+	assert.Equal(t, SetTableResponseType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(1), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeSetTableResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*SetTableResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeSetTableResponse, response.LayerType())
+	assert.Equal(t, LayerTypeSetTableResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, me.ProcessingError, response.Result)
+	assert.Equal(t, me.ExtendedVlanTaggingOperationConfigurationDataClassID, response.EntityClass)
+	assert.Equal(t, uint16(0x1234), response.EntityInstance)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestSetTableResponseSerialize(t *testing.T) {
+	goodMessage := "01073d0b00ab1234000103"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0107,
+		MessageType:      SetTableResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &SetTableResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x1234),
+			Extended:       true,
+		},
+		Result: me.ParameterError,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestSetTableResponseZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID:    0x0,
+		MessageType:      SetTableResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &SetTableResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.ExtendedVlanTaggingOperationConfigurationDataClassID,
+			EntityInstance: uint16(0x1234),
+			Extended:       true,
+		},
+		Result: me.ParameterError,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
diff --git a/software.go b/software.go
new file mode 100644
index 0000000..de5cb74
--- /dev/null
+++ b/software.go
@@ -0,0 +1,1328 @@
+/*
+ * 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"
+	"github.com/google/gopacket"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+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)
+}
+
+// LayerType returns LayerTypeStartSoftwareDownloadRequest
+func (omci *StartSoftwareDownloadRequest) LayerType() gopacket.LayerType {
+	return LayerTypeStartSoftwareDownloadRequest
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *StartSoftwareDownloadRequest) CanDecode() gopacket.LayerClass {
+	return LayerTypeStartSoftwareDownloadRequest
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *StartSoftwareDownloadRequest) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// DecodeFromBytes decodes the given bytes of a Start Software Download Request into this layer
+func (omci *StartSoftwareDownloadRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6 + 4
+	} else {
+		hdrSize = 4 + 4
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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")
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	omci.WindowSize = data[offset+4]
+	omci.ImageSize = binary.BigEndian.Uint32(data[offset+5:])
+	omci.NumberOfCircuitPacks = data[offset+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[offset+10+(index*2):])
+	}
+	return nil
+}
+
+func decodeStartSoftwareDownloadRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &StartSoftwareDownloadRequest{}
+	omci.MsgLayerType = LayerTypeStartSoftwareDownloadRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+func decodeStartSoftwareDownloadRequestExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &StartSoftwareDownloadRequest{}
+	omci.MsgLayerType = LayerTypeStartSoftwareDownloadRequest
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Start Software Download Request message
+func (omci *StartSoftwareDownloadRequest) SerializeTo(b gopacket.SerializeBuffer, _ 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 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")
+	}
+	if omci.NumberOfCircuitPacks < 1 || omci.NumberOfCircuitPacks > 9 {
+		return me.NewProcessingError(fmt.Sprintf("invalid number of Circuit Packs: %v, must be 1..9",
+			omci.NumberOfCircuitPacks))
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	bytes, err := b.AppendBytes(offset + 6 + (2 * int(omci.NumberOfCircuitPacks)))
+	if err != nil {
+		return err
+	}
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, uint16(6+(2*int(omci.NumberOfCircuitPacks))))
+	}
+	bytes[offset] = omci.WindowSize
+	binary.BigEndian.PutUint32(bytes[offset+1:], omci.ImageSize)
+	bytes[offset+5] = omci.NumberOfCircuitPacks
+	for index := 0; index < int(omci.NumberOfCircuitPacks); index++ {
+		binary.BigEndian.PutUint16(bytes[offset+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)
+}
+
+// LayerType returns LayerTypeStartSoftwareDownloadResponse
+func (omci *StartSoftwareDownloadResponse) LayerType() gopacket.LayerType {
+	return LayerTypeStartSoftwareDownloadResponse
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *StartSoftwareDownloadResponse) CanDecode() gopacket.LayerClass {
+	return LayerTypeStartSoftwareDownloadResponse
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *StartSoftwareDownloadResponse) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6 + 3
+	} else {
+		hdrSize = 4 + 3
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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")
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	omci.Result = me.Results(data[offset+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[offset+5]
+	omci.NumberOfInstances = data[offset+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 {
+		// TODO: Calculate additional space needed and see if it is truncated
+		omci.MeResults = make([]DownloadResults, omci.NumberOfInstances)
+
+		for index := 0; index < int(omci.NumberOfInstances); index++ {
+			omci.MeResults[index].ManagedEntityID = binary.BigEndian.Uint16(data[offset+7+(index*3):])
+			omci.MeResults[index].Result = me.Results(data[offset+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)
+}
+
+func decodeStartSoftwareDownloadResponseExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &StartSoftwareDownloadResponse{}
+	omci.MsgLayerType = LayerTypeStartSoftwareDownloadResponse
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Start Software Download Response message
+func (omci *StartSoftwareDownloadResponse) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	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)
+	}
+	if omci.NumberOfInstances > 9 {
+		msg := fmt.Sprintf("invalid number of Circuit Packs: %v, must be 0..9",
+			omci.NumberOfInstances)
+		return errors.New(msg)
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	bytes, err := b.AppendBytes(offset + 3 + (3 * int(omci.NumberOfInstances)))
+	if err != nil {
+		return err
+	}
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, uint16(3+(3*int(omci.NumberOfInstances))))
+	}
+	bytes[offset] = byte(omci.Result)
+	bytes[offset+1] = omci.WindowSize
+	bytes[offset+2] = omci.NumberOfInstances
+
+	if omci.NumberOfInstances > 0 {
+		for index := 0; index < int(omci.NumberOfInstances); index++ {
+			binary.BigEndian.PutUint16(bytes[offset+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[offset+5+(3*index)] = byte(omci.MeResults[index].Result)
+		}
+	}
+	return nil
+}
+
+// DownloadSectionRequest data is bound by the message set in use. For the
+// Baseline message set use MaxDownloadSectionLength and for the Extended message
+// set, MaxDownloadSectionExtendedLength is provided
+type DownloadSectionRequest struct {
+	MeBasePacket  // Note: EntityInstance for software download is two specific values
+	SectionNumber byte
+	SectionData   []byte // 0 padding if final transfer requires only a partial block for baseline set
+}
+
+func (omci *DownloadSectionRequest) String() string {
+	return fmt.Sprintf("%v, Section #: %v, Data Length: %v",
+		omci.MeBasePacket.String(), omci.SectionNumber, len(omci.SectionData))
+}
+
+// LayerType returns LayerTypeDownloadSectionRequest
+func (omci *DownloadSectionRequest) LayerType() gopacket.LayerType {
+	return LayerTypeDownloadSectionRequest
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *DownloadSectionRequest) CanDecode() gopacket.LayerClass {
+	return LayerTypeDownloadSectionRequest
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *DownloadSectionRequest) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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, 4+1)
+	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")
+	}
+	if omci.Extended {
+		if len(data) < 7 {
+			p.SetTruncated()
+			return errors.New("frame too small")
+		}
+		if len(data[7:]) > MaxDownloadSectionExtendedLength {
+			return errors.New(fmt.Sprintf("software image data too large. Received %v, Max: %v",
+				len(data[7:]), MaxDownloadSectionExtendedLength))
+		}
+		omci.SectionData = make([]byte, len(data[7:]))
+		omci.SectionNumber = data[6]
+		copy(omci.SectionData, data[7:])
+	} else {
+		if len(data[5:]) != MaxDownloadSectionLength {
+			p.SetTruncated()
+			return errors.New(fmt.Sprintf("software image size invalid. Received %v, Expected: %v",
+				len(data[5:]), MaxDownloadSectionLength))
+		}
+		omci.SectionData = make([]byte, MaxDownloadSectionLength)
+		omci.SectionNumber = data[4]
+		copy(omci.SectionData, data[5:])
+	}
+	return nil
+}
+
+func decodeDownloadSectionRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &DownloadSectionRequest{}
+	omci.MsgLayerType = LayerTypeDownloadSectionRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+func decodeDownloadSectionRequestExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &DownloadSectionRequest{}
+	omci.MsgLayerType = LayerTypeDownloadSectionRequest
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Download Section Request message
+func (omci *DownloadSectionRequest) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	sectionLength := len(omci.SectionData)
+	if omci.Extended {
+		if sectionLength > MaxDownloadSectionExtendedLength {
+			msg := fmt.Sprintf("invalid Download Section data length, must be <= %v, received: %v",
+				MaxDownloadSectionExtendedLength, sectionLength)
+			return me.NewProcessingError(msg)
+		}
+		// Append section data
+		bytes, err := b.AppendBytes(3 + sectionLength)
+		if err != nil {
+			return err
+		}
+		binary.BigEndian.PutUint16(bytes, uint16(1+sectionLength))
+		bytes[2] = omci.SectionNumber
+		copy(bytes[3:], omci.SectionData)
+	} else {
+		if sectionLength > MaxDownloadSectionLength {
+			msg := fmt.Sprintf("invalid Download Section data length, must be <= %v, received: %v",
+				MaxDownloadSectionLength, sectionLength)
+			return me.NewProcessingError(msg)
+		}
+		// Append section data
+		bytes, err := b.AppendBytes(1 + MaxDownloadSectionLength)
+		if err != nil {
+			return err
+		}
+		bytes[0] = omci.SectionNumber
+		copy(bytes[1:], omci.SectionData)
+
+		// Zero extended if needed
+		if sectionLength < MaxDownloadSectionLength {
+			copy(omci.SectionData[sectionLength:], lotsOfZeros[:MaxDownloadSectionLength-sectionLength])
+		}
+	}
+	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)
+}
+
+// LayerType returns LayerTypeDownloadSectionResponse
+func (omci *DownloadSectionResponse) LayerType() gopacket.LayerType {
+	return LayerTypeDownloadSectionResponse
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *DownloadSectionResponse) CanDecode() gopacket.LayerClass {
+	return LayerTypeDownloadSectionResponse
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *DownloadSectionResponse) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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, 4+2)
+	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")
+	}
+	if omci.Extended {
+		if len(data) < 8 {
+			p.SetTruncated()
+			return errors.New("frame too small")
+		}
+		omci.Result = me.Results(data[6])
+		omci.SectionNumber = data[7]
+	} else {
+		omci.Result = me.Results(data[4])
+		omci.SectionNumber = data[5]
+	}
+	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)
+	}
+	return nil
+}
+
+func decodeDownloadSectionResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &DownloadSectionResponse{}
+	omci.MsgLayerType = LayerTypeDownloadSectionResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+func decodeDownloadSectionResponseExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &DownloadSectionResponse{}
+	omci.MsgLayerType = LayerTypeDownloadSectionResponse
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Download Section Response message
+func (omci *DownloadSectionResponse) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	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)
+	}
+	if omci.Extended {
+		bytes, err := b.AppendBytes(4)
+		if err != nil {
+			return err
+		}
+		binary.BigEndian.PutUint16(bytes, uint16(2))
+		bytes[2] = byte(omci.Result)
+		bytes[3] = omci.SectionNumber
+	} else {
+		bytes, err := b.AppendBytes(2)
+		if err != nil {
+			return err
+		}
+		bytes[0] = byte(omci.Result)
+		bytes[1] = omci.SectionNumber
+	}
+	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)
+}
+
+// LayerType returns LayerTypeEndSoftwareDownloadRequest
+func (omci *EndSoftwareDownloadRequest) LayerType() gopacket.LayerType {
+	return LayerTypeEndSoftwareDownloadRequest
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *EndSoftwareDownloadRequest) CanDecode() gopacket.LayerClass {
+	return LayerTypeEndSoftwareDownloadRequest
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *EndSoftwareDownloadRequest) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6 + 7
+	} else {
+		hdrSize = 4 + 7
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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")
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	omci.CRC32 = binary.BigEndian.Uint32(data[offset+4:])
+	omci.ImageSize = binary.BigEndian.Uint32(data[offset+8:])
+	omci.NumberOfInstances = data[offset+12]
+
+	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[offset+13+(index*2):])
+	}
+	return nil
+}
+
+func decodeEndSoftwareDownloadRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &EndSoftwareDownloadRequest{}
+	omci.MsgLayerType = LayerTypeEndSoftwareDownloadRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+func decodeEndSoftwareDownloadRequestExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &EndSoftwareDownloadRequest{}
+	omci.MsgLayerType = LayerTypeEndSoftwareDownloadRequest
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an End Software Download Request message
+func (omci *EndSoftwareDownloadRequest) SerializeTo(b gopacket.SerializeBuffer, _ 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))
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	bytes, err := b.AppendBytes(offset + 9 + (2 * int(omci.NumberOfInstances)))
+	if err != nil {
+		return err
+	}
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, uint16(9+(2*int(omci.NumberOfInstances))))
+	}
+	binary.BigEndian.PutUint32(bytes[offset+0:], omci.CRC32)
+	binary.BigEndian.PutUint32(bytes[offset+4:], omci.ImageSize)
+	bytes[offset+8] = omci.NumberOfInstances
+	for index := 0; index < int(omci.NumberOfInstances); index++ {
+		binary.BigEndian.PutUint16(bytes[offset+9+(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)
+}
+
+// LayerType returns LayerTypeCreateResponse
+func (omci *EndSoftwareDownloadResponse) LayerType() gopacket.LayerType {
+	return LayerTypeEndSoftwareDownloadResponse
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *EndSoftwareDownloadResponse) CanDecode() gopacket.LayerClass {
+	return LayerTypeEndSoftwareDownloadResponse
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *EndSoftwareDownloadResponse) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6 + 2
+	} else {
+		hdrSize = 4 + 2
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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")
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	omci.Result = me.Results(data[offset+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[offset+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[offset+6+(index*3):])
+			omci.MeResults[index].Result = me.Results(data[offset+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)
+}
+
+func decodeEndSoftwareDownloadResponseExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &EndSoftwareDownloadResponse{}
+	omci.MsgLayerType = LayerTypeEndSoftwareDownloadResponse
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an End Software Download Response message
+func (omci *EndSoftwareDownloadResponse) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	bytes, err := b.AppendBytes(offset + 2 + (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)
+	}
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, uint16(2+(3*int(omci.NumberOfInstances))))
+	}
+	bytes[offset] = byte(omci.Result)
+	bytes[offset+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[offset+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[offset+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)
+}
+
+// LayerType returns LayerTypeActivateSoftwareRequest
+func (omci *ActivateSoftwareRequest) LayerType() gopacket.LayerType {
+	return LayerTypeActivateSoftwareRequest
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *ActivateSoftwareRequest) CanDecode() gopacket.LayerClass {
+	return LayerTypeActivateSoftwareRequest
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *ActivateSoftwareRequest) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6 + 1
+	} else {
+		hdrSize = 4 + 1
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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")
+	}
+	if omci.Extended {
+		omci.ActivateFlags = data[6]
+	} else {
+		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)
+}
+
+func decodeActivateSoftwareRequestExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &ActivateSoftwareRequest{}
+	omci.MsgLayerType = LayerTypeActivateSoftwareRequest
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Activate Software message
+func (omci *ActivateSoftwareRequest) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	bytes, err := b.AppendBytes(offset + 1)
+	if err != nil {
+		return err
+	}
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, uint16(1))
+	}
+	bytes[offset] = 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)
+}
+
+// LayerType returns LayerTypeActivateSoftwareResponse
+func (omci *ActivateSoftwareResponse) LayerType() gopacket.LayerType {
+	return LayerTypeActivateSoftwareResponse
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *ActivateSoftwareResponse) CanDecode() gopacket.LayerClass {
+	return LayerTypeActivateSoftwareResponse
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *ActivateSoftwareResponse) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// DecodeFromBytes decodes the given bytes of an Activate Software Response into this layer
+func (omci *ActivateSoftwareResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6 + 1
+	} else {
+		hdrSize = 4 + 1
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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")
+	}
+	if omci.Extended {
+		omci.Result = me.Results(data[6])
+	} else {
+		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)
+}
+
+func decodeActivateSoftwareResponseExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &ActivateSoftwareResponse{}
+	omci.MsgLayerType = LayerTypeActivateSoftwareResponse
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Activate Software Response message
+func (omci *ActivateSoftwareResponse) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	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)
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	bytes, err := b.AppendBytes(offset + 1)
+	if err != nil {
+		return err
+	}
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, 1)
+	}
+	bytes[offset] = byte(omci.Result)
+	return nil
+}
+
+type CommitSoftwareRequest struct {
+	MeBasePacket
+}
+
+func (omci *CommitSoftwareRequest) String() string {
+	return fmt.Sprintf("%v", omci.MeBasePacket.String())
+}
+
+// LayerType returns LayerTypeCommitSoftwareRequest
+func (omci *CommitSoftwareRequest) LayerType() gopacket.LayerType {
+	return LayerTypeCommitSoftwareRequest
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *CommitSoftwareRequest) CanDecode() gopacket.LayerClass {
+	return LayerTypeCommitSoftwareRequest
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *CommitSoftwareRequest) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6
+	} else {
+		hdrSize = 4
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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)
+}
+
+func decodeCommitSoftwareRequestExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &CommitSoftwareRequest{}
+	omci.MsgLayerType = LayerTypeCommitSoftwareRequest
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Commit Software Request message
+func (omci *CommitSoftwareRequest) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	if omci.Extended {
+		bytes, err := b.AppendBytes(2)
+		if err != nil {
+			return err
+		}
+		binary.BigEndian.PutUint16(bytes, 0)
+	}
+	return nil
+}
+
+type CommitSoftwareResponse struct {
+	MeBasePacket
+	Result me.Results
+}
+
+func (omci *CommitSoftwareResponse) String() string {
+	return fmt.Sprintf("%v", omci.MeBasePacket.String())
+}
+
+// LayerType returns LayerTypeCommitSoftwareResponse
+func (omci *CommitSoftwareResponse) LayerType() gopacket.LayerType {
+	return LayerTypeCommitSoftwareResponse
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *CommitSoftwareResponse) CanDecode() gopacket.LayerClass {
+	return LayerTypeCommitSoftwareResponse
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *CommitSoftwareResponse) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// DecodeFromBytes decodes the given bytes of a Commit Software Response into this layer
+func (omci *CommitSoftwareResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	var hdrSize int
+	if omci.Extended {
+		hdrSize = 6 + 1
+	} else {
+		hdrSize = 4 + 1
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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 Commit Software
+	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")
+	}
+	if omci.Extended {
+		omci.Result = me.Results(data[6])
+	} else {
+		omci.Result = me.Results(data[4])
+	}
+	if omci.Result > me.Results(6) {
+		msg := fmt.Sprintf("invalid results for Commit Software response: %v, must be 0..6",
+			omci.Result)
+		return errors.New(msg)
+	}
+	return nil
+}
+
+func decodeCommitSoftwareResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &CommitSoftwareResponse{}
+	omci.MsgLayerType = LayerTypeCommitSoftwareResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+func decodeCommitSoftwareResponseExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &CommitSoftwareResponse{}
+	omci.MsgLayerType = LayerTypeCommitSoftwareResponse
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Commit Software Response message
+func (omci *CommitSoftwareResponse) SerializeTo(b gopacket.SerializeBuffer, _ 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 Commit Software
+	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")
+	}
+	if omci.Result > me.Results(6) {
+		msg := fmt.Sprintf("invalid results for Commit Software response: %v, must be 0..6",
+			omci.Result)
+		return errors.New(msg)
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	}
+	bytes, err := b.AppendBytes(offset + 1)
+	if err != nil {
+		return err
+	}
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, 1)
+		bytes[2] = byte(omci.Result)
+	} else {
+		bytes[0] = byte(omci.Result)
+	}
+	return nil
+}
diff --git a/software_test.go b/software_test.go
new file mode 100644
index 0000000..dc0fb93
--- /dev/null
+++ b/software_test.go
@@ -0,0 +1,2027 @@
+/*
+ * 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_test
+
+import (
+	"fmt"
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/stretchr/testify/assert"
+	"strings"
+	"testing"
+)
+
+func TestStartSoftwareDownloadRequestDecode(t *testing.T) {
+	goodMessage := "0004530a00070001ff000f424001000100000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeStartSoftwareDownloadRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0004), omciMsg.TransactionID)
+	assert.Equal(t, StartSoftwareDownloadRequestType, omciMsg.MessageType)
+	assert.True(t, omciMsg.ResponseExpected)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeStartSoftwareDownloadRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*StartSoftwareDownloadRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeStartSoftwareDownloadRequest, request.LayerType())
+	assert.Equal(t, LayerTypeStartSoftwareDownloadRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, uint8(0xff), request.WindowSize)
+	assert.Equal(t, uint32(0x000f4240), request.ImageSize)
+	assert.Equal(t, uint8(1), request.NumberOfCircuitPacks)
+	assert.NotNil(t, request.CircuitPacks)
+	assert.Equal(t, 1, len(request.CircuitPacks))
+	assert.Equal(t, uint16(1), request.CircuitPacks[0])
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestStartSoftwareDownloadRequestDecodeExtended(t *testing.T) {
+	goodMessage := "0004530b000700010008ff000f4240010001"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeStartSoftwareDownloadRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0004), omciMsg.TransactionID)
+	assert.Equal(t, StartSoftwareDownloadRequestType, omciMsg.MessageType)
+	assert.True(t, omciMsg.ResponseExpected)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(8), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeStartSoftwareDownloadRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*StartSoftwareDownloadRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeStartSoftwareDownloadRequest, request.LayerType())
+	assert.Equal(t, LayerTypeStartSoftwareDownloadRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, uint8(0xff), request.WindowSize)
+	assert.Equal(t, uint32(0x000f4240), request.ImageSize)
+	assert.Equal(t, uint8(1), request.NumberOfCircuitPacks)
+	assert.NotNil(t, request.CircuitPacks)
+	assert.Equal(t, 1, len(request.CircuitPacks))
+	assert.Equal(t, uint16(1), request.CircuitPacks[0])
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestStartSoftwareDownloadRequestSerialize(t *testing.T) {
+	goodMessage := "0004530a00070001ff000f424001000100000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x04,
+		MessageType:   StartSoftwareDownloadRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &StartSoftwareDownloadRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 1,
+		},
+		WindowSize:           255,
+		ImageSize:            0x000f4240,
+		NumberOfCircuitPacks: 1,
+		CircuitPacks:         []uint16{0x0001},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestStartSoftwareDownloadRequestZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   StartSoftwareDownloadRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &StartSoftwareDownloadRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 1,
+		},
+		WindowSize:           255,
+		ImageSize:            0x000f4240,
+		NumberOfCircuitPacks: 1,
+		CircuitPacks:         []uint16{0x0001},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestStartSoftwareDownloadRequestSerializeExtended(t *testing.T) {
+	goodMessage := "0004530b000700010008ff000f4240010001"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x04,
+		MessageType:      StartSoftwareDownloadRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &StartSoftwareDownloadRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 1,
+			Extended:       true,
+		},
+		WindowSize:           255,
+		ImageSize:            0x000f4240,
+		NumberOfCircuitPacks: 1,
+		CircuitPacks:         []uint16{0x0001},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestStartSoftwareDownloadResponseDecode(t *testing.T) {
+	goodMessage := "0004330a0007000100ff00000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, omciMsg.TransactionID, uint16(0x0004))
+	assert.Equal(t, omciMsg.MessageType, StartSoftwareDownloadResponseType)
+	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
+	assert.Equal(t, omciMsg.Length, uint16(40))
+
+	msgLayer := packet.Layer(LayerTypeStartSoftwareDownloadResponse)
+
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*StartSoftwareDownloadResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, me.Success, response.Result)
+	assert.Equal(t, uint8(0xff), response.WindowSize)
+	assert.Equal(t, uint8(0), response.NumberOfInstances)
+	assert.Nil(t, response.MeResults)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestStartSoftwareDownloadResponseDecodeExtended(t *testing.T) {
+	goodMessage := "0004330b00070001000300ff00"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, uint16(0x0004), omciMsg.TransactionID)
+	assert.Equal(t, StartSoftwareDownloadResponseType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(3), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeStartSoftwareDownloadResponse)
+
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*StartSoftwareDownloadResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, me.Success, response.Result)
+	assert.Equal(t, uint8(0xff), response.WindowSize)
+	assert.Equal(t, uint8(0), response.NumberOfInstances)
+	assert.Nil(t, response.MeResults)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestStartSoftwareDownloadResponseSerialize(t *testing.T) {
+	goodMessage := "0001330a0007000100ff00000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x01,
+		MessageType:   StartSoftwareDownloadResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &StartSoftwareDownloadResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 1,
+		},
+		Result:            me.Success,
+		WindowSize:        0xff,
+		NumberOfInstances: 0,   // Note: Optional since default is zero
+		MeResults:         nil, // Note: Optional since default is nil
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestStartSoftwareDownloadResponseZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   StartSoftwareDownloadResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &StartSoftwareDownloadResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 1,
+		},
+		Result:            me.Success,
+		WindowSize:        0xff,
+		NumberOfInstances: 0,   // Note: Optional since default is zero
+		MeResults:         nil, // Note: Optional since default is nil
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestStartSoftwareDownloadResponseSerializeExtended(t *testing.T) {
+	goodMessage := "0001330b00070001000300ff00"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x01,
+		MessageType:      StartSoftwareDownloadResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &StartSoftwareDownloadResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 1,
+			Extended:       true,
+		},
+		Result:            me.Success,
+		WindowSize:        0xff,
+		NumberOfInstances: 0,   // Note: Optional since default is zero
+		MeResults:         nil, // Note: Optional since default is nil
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestDownloadSectionRequestDecodeNoResponseExpected(t *testing.T) {
+	goodMessage := "0008140a00070001cc0102030405060708091011121314151617181920212223242526272829303100000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeDownloadSectionRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0008), omciMsg.TransactionID)
+	assert.Equal(t, DownloadSectionRequestType, omciMsg.MessageType)
+	assert.False(t, omciMsg.ResponseExpected)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeDownloadSectionRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*DownloadSectionRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeDownloadSectionRequest, request.LayerType())
+	assert.Equal(t, LayerTypeDownloadSectionRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, uint8(0xcc), request.SectionNumber)
+	assert.Equal(t, MaxDownloadSectionLength, len(request.SectionData))
+
+	sectionData, genErr := stringToPacket("01020304050607080910111213141516171819202122232425262728293031")
+	assert.Nil(t, genErr)
+	assert.NotNil(t, sectionData)
+	assert.Equal(t, MaxDownloadSectionLength, len(sectionData))
+	assert.Equal(t, sectionData, request.SectionData[:])
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestDownloadSectionRequestDecodeResponseExpected(t *testing.T) {
+	goodMessage := "0008540a00070001cc0102030405060708091011121314151617181920212223242526272829303100000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeDownloadSectionLastRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0008), omciMsg.TransactionID)
+	assert.Equal(t, DownloadSectionRequestWithResponseType, omciMsg.MessageType)
+	assert.True(t, omciMsg.ResponseExpected)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeDownloadSectionRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*DownloadSectionRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeDownloadSectionRequest, request.LayerType())
+	assert.Equal(t, LayerTypeDownloadSectionRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, uint8(0xcc), request.SectionNumber)
+	assert.Equal(t, 31, len(request.SectionData))
+
+	sectionData, genErr := stringToPacket("01020304050607080910111213141516171819202122232425262728293031")
+	assert.Nil(t, genErr)
+	assert.NotNil(t, sectionData)
+	assert.Equal(t, MaxDownloadSectionLength, len(sectionData))
+	assert.Equal(t, sectionData, request.SectionData[:])
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestDownloadSectionRequestSerializeNoResponseExpected(t *testing.T) {
+	goodMessage := "0123140a00070000cc0102030405060708091011121314151617181920212223242526272829303100000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x0123,
+		MessageType:   DownloadSectionRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	sectionData, genErr := stringToPacket("01020304050607080910111213141516171819202122232425262728293031")
+	assert.Nil(t, genErr)
+	assert.NotNil(t, sectionData)
+	assert.Equal(t, MaxDownloadSectionLength, len(sectionData))
+
+	request := &DownloadSectionRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass: me.SoftwareImageClassID,
+			// Default Instance ID is 0
+		},
+		SectionNumber: 0xcc,
+		SectionData:   sectionData,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestDownloadSectionRequestSerializeNoResponsePartialDataExpected(t *testing.T) {
+	// If a small buffer is provided, serialize will now zero extend the baseline format
+	goodMessage := "0123140a00070000cc0102030405060708091011121314151617181920212223242526272829000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x0123,
+		MessageType:   DownloadSectionRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	sectionData, genErr := stringToPacket("0102030405060708091011121314151617181920212223242526272829")
+	assert.Nil(t, genErr)
+	assert.NotNil(t, sectionData)
+	assert.Equal(t, MaxDownloadSectionLength-2, len(sectionData)) // Partial data buffer
+
+	request := &DownloadSectionRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass: me.SoftwareImageClassID,
+			// Default Instance ID is 0
+		},
+		SectionNumber: 0xcc,
+		SectionData:   sectionData,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestDownloadSectionRequestSerializeResponseExpectedMethod1(t *testing.T) {
+	goodMessage := "2468540a00070000cc0102030405060708091011121314151617181920212223242526272829303100000028"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x2468,
+		MessageType:      DownloadSectionRequestType, // or DownloadSectionRequestWithResponseType
+		ResponseExpected: true,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	sectionData, genErr := stringToPacket("01020304050607080910111213141516171819202122232425262728293031")
+	assert.Nil(t, genErr)
+	assert.NotNil(t, sectionData)
+	assert.Equal(t, MaxDownloadSectionLength, len(sectionData))
+
+	request := &DownloadSectionRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass: me.SoftwareImageClassID,
+			// Default Instance ID is 0
+		},
+		SectionNumber: 0xcc,
+		SectionData:   sectionData,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestDownloadSectionRequestSerializeResponseExpectedMethod2(t *testing.T) {
+	goodMessage := "2468540a00070001cc0102030405060708091011121314151617181920212223242526272829303100000028"
+
+	// In this case, just use the request type with AR response requested already encoded
+	omciLayer := &OMCI{
+		TransactionID: 0x2468,
+		MessageType:   DownloadSectionRequestWithResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	sectionData, genErr := stringToPacket("01020304050607080910111213141516171819202122232425262728293031")
+	assert.Nil(t, genErr)
+	assert.NotNil(t, sectionData)
+	assert.Equal(t, MaxDownloadSectionLength, len(sectionData))
+
+	request := &DownloadSectionRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 0x0001, // Default is zero, here we want image 1
+		},
+		SectionNumber: 0xcc,
+		SectionData:   sectionData,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestDownloadSectionRequestSerializeResponseExpectedZeroTICMethod1(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID:    0x0,
+		MessageType:      DownloadSectionRequestType, // or DownloadSectionRequestWithResponseType
+		ResponseExpected: true,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	sectionData, genErr := stringToPacket("01020304050607080910111213141516171819202122232425262728293031")
+	assert.Nil(t, genErr)
+	assert.NotNil(t, sectionData)
+	assert.Equal(t, MaxDownloadSectionLength, len(sectionData))
+
+	request := &DownloadSectionRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass: me.SoftwareImageClassID,
+			// Default Instance ID is 0
+		},
+		SectionNumber: 0xcc,
+		SectionData:   sectionData,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestExtendedDownloadSectionRequestDecodeNoResponseExpected(t *testing.T) {
+	goodMessage := "0008140b00070001"
+	payloadFragment := "01020304050607080910111213141516171819202122232425"
+	payloadTotal := payloadFragment + payloadFragment + payloadFragment + payloadFragment +
+		payloadFragment + payloadFragment + payloadFragment + payloadFragment
+	sectionNumber := 0x88
+	length := 1 + (8 * 25)
+	hdr := fmt.Sprintf("%04x%02x", length, sectionNumber)
+	goodMessage += hdr + payloadTotal
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+	assert.Nil(t, packet.ErrorLayer())
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeDownloadSectionRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0008), omciMsg.TransactionID)
+	assert.Equal(t, DownloadSectionRequestType, omciMsg.MessageType)
+	assert.False(t, omciMsg.ResponseExpected)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(length), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeDownloadSectionRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*DownloadSectionRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeDownloadSectionRequest, request.LayerType())
+	assert.Equal(t, LayerTypeDownloadSectionRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, uint8(sectionNumber), request.SectionNumber)
+	assert.Equal(t, length-1, len(request.SectionData))
+
+	data, err = stringToPacket(payloadTotal)
+	assert.NoError(t, err)
+	assert.Equal(t, data, request.SectionData[:])
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedDownloadSectionRequestDecodeResponseExpected(t *testing.T) {
+	goodMessage := "0008540b00070001"
+	payloadFragment := "01020304050607080910111213141516171819202122232425"
+	payloadTotal := payloadFragment + payloadFragment + payloadFragment + payloadFragment +
+		payloadFragment + payloadFragment + payloadFragment + payloadFragment +
+		payloadFragment + payloadFragment + payloadFragment + payloadFragment +
+		payloadFragment + payloadFragment + payloadFragment + payloadFragment +
+		payloadFragment + payloadFragment + payloadFragment + payloadFragment
+	sectionNumber := 0x88
+	length := 1 + (20 * 25)
+	hdr := fmt.Sprintf("%04x%02x", length, sectionNumber)
+	goodMessage += hdr + payloadTotal
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+	assert.Nil(t, packet.ErrorLayer())
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, uint16(0x0008), omciMsg.TransactionID)
+	assert.Equal(t, DownloadSectionRequestWithResponseType, omciMsg.MessageType)
+	assert.True(t, omciMsg.ResponseExpected)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(length), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeDownloadSectionRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*DownloadSectionRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, uint8(sectionNumber), request.SectionNumber)
+	assert.Equal(t, length-1, len(request.SectionData))
+
+	data, err = stringToPacket(payloadTotal)
+	assert.NoError(t, err)
+	assert.Equal(t, data, request.SectionData)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedDownloadSectionRequestSerializeNoResponseExpected(t *testing.T) {
+	goodMessage := "0123140b00070001"
+	payloadFragment := "01020304050607080910111213141516171819202122232425"
+	payloadTotal := payloadFragment + payloadFragment + payloadFragment + payloadFragment +
+		payloadFragment + payloadFragment + payloadFragment + payloadFragment
+	sectionNumber := 0x84
+	length := 1 + (8 * 25)
+	hdr := fmt.Sprintf("%04x%02x", length, sectionNumber)
+	goodMessage += hdr + payloadTotal
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0123,
+		MessageType:      DownloadSectionRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	sectionData, genErr := stringToPacket(payloadTotal)
+	assert.Nil(t, genErr)
+	assert.NotNil(t, sectionData)
+	assert.Equal(t, len(payloadTotal)/2, len(sectionData))
+
+	request := &DownloadSectionRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: uint16(1),
+			Extended:       true,
+		},
+		SectionNumber: byte(sectionNumber),
+		SectionData:   sectionData,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestExtendedDownloadSectionRequestSerializeResponseExpectedMethod1(t *testing.T) {
+	goodMessage := "2468540b00070001"
+	payloadFragment := "01020304050607080910111213141516171819202122232425"
+	payloadTotal := payloadFragment + payloadFragment + payloadFragment + payloadFragment +
+		payloadFragment + payloadFragment + payloadFragment + payloadFragment
+	sectionNumber := 0x84
+	length := 1 + (8 * 25)
+	hdr := fmt.Sprintf("%04x%02x", length, sectionNumber)
+	goodMessage += hdr + payloadTotal
+
+	omciLayer := &OMCI{
+		TransactionID:    0x2468,
+		MessageType:      DownloadSectionRequestType, // or DownloadSectionRequestWithResponseType
+		ResponseExpected: true,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	sectionData, genErr := stringToPacket(payloadTotal)
+	assert.Nil(t, genErr)
+	assert.NotNil(t, sectionData)
+	assert.Equal(t, len(payloadTotal)/2, len(sectionData))
+
+	request := &DownloadSectionRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: uint16(1),
+			Extended:       true,
+		},
+		SectionNumber: byte(sectionNumber),
+		SectionData:   sectionData,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestExtendedDownloadSectionRequestSerializeResponseExpectedMethod2(t *testing.T) {
+	goodMessage := "2468540b00070001"
+	payloadFragment := "01020304050607080910111213141516171819202122232425"
+	payloadTotal := payloadFragment + payloadFragment + payloadFragment + payloadFragment +
+		payloadFragment + payloadFragment + payloadFragment + payloadFragment
+	sectionNumber := 0x84
+	length := 1 + (8 * 25)
+	hdr := fmt.Sprintf("%04x%02x", length, sectionNumber)
+	goodMessage += hdr + payloadTotal
+
+	// In this case, just use the request type with AR response requested already encoded
+	omciLayer := &OMCI{
+		TransactionID:    0x2468,
+		MessageType:      DownloadSectionRequestWithResponseType,
+		ResponseExpected: true,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	sectionData, genErr := stringToPacket(payloadTotal)
+	assert.Nil(t, genErr)
+	assert.NotNil(t, sectionData)
+	assert.Equal(t, len(payloadTotal)/2, len(sectionData))
+
+	request := &DownloadSectionRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 0x0001, // Default is zero, here we want image 1
+			Extended:       true,
+		},
+		SectionNumber: byte(sectionNumber),
+		SectionData:   sectionData,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestExtendedDownloadSectionRequestDecodeTruncated(t *testing.T) {
+	goodMessage := "0008540b000700010000"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	failure := packet.ErrorLayer()
+	assert.NotNil(t, failure)
+
+	decodeFailure, ok := failure.(*gopacket.DecodeFailure)
+	assert.True(t, ok)
+	assert.NotNil(t, decodeFailure)
+	assert.NotNil(t, decodeFailure.String())
+	assert.True(t, len(decodeFailure.String()) > 0)
+	assert.Equal(t, gopacket.LayerTypeDecodeFailure, decodeFailure.LayerType())
+
+	metadata := packet.Metadata()
+	assert.NotNil(t, metadata)
+	assert.True(t, metadata.Truncated)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestDownloadSectionResponseDecode(t *testing.T) {
+	goodMessage := "0022340a00070001061f00000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeDownloadSectionResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0022), omciMsg.TransactionID)
+	assert.Equal(t, DownloadSectionResponseType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeDownloadSectionResponse)
+
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*DownloadSectionResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeDownloadSectionResponse, response.LayerType())
+	assert.Equal(t, LayerTypeDownloadSectionResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, me.DeviceBusy, response.Result)
+	assert.Equal(t, byte(0x1f), response.SectionNumber)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestDownloadSectionResponseDecodeExtended(t *testing.T) {
+	goodMessage := "0022340b000700010002061f"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeDownloadSectionResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0022), omciMsg.TransactionID)
+	assert.Equal(t, DownloadSectionResponseType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(2), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeDownloadSectionResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*DownloadSectionResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeDownloadSectionResponse, response.LayerType())
+	assert.Equal(t, LayerTypeDownloadSectionResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, me.DeviceBusy, response.Result)
+	assert.Equal(t, byte(0x1f), response.SectionNumber)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestDownloadSectionResponseDecodeTruncatedExtended(t *testing.T) {
+	goodMessage := "0022340b00070001000106"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	failure := packet.ErrorLayer()
+	assert.NotNil(t, failure)
+
+	decodeFailure, ok := failure.(*gopacket.DecodeFailure)
+	assert.True(t, ok)
+	assert.NotNil(t, decodeFailure)
+	assert.NotNil(t, decodeFailure.String())
+	assert.True(t, len(decodeFailure.String()) > 0)
+	assert.Equal(t, gopacket.LayerTypeDecodeFailure, decodeFailure.LayerType())
+
+	metadata := packet.Metadata()
+	assert.NotNil(t, metadata)
+	assert.True(t, metadata.Truncated)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestDownloadSectionResponseSerialize(t *testing.T) {
+	goodMessage := "0022340a00070001061f00000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x0022,
+		MessageType:   DownloadSectionResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &DownloadSectionResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 1,
+		},
+		Result:        me.DeviceBusy,
+		SectionNumber: 0x1f,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestDownloadSectionResponseZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   DownloadSectionResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &DownloadSectionResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 1,
+		},
+		Result:        me.DeviceBusy,
+		SectionNumber: 0x1f,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestDownloadSectionResponseSerializeExtended(t *testing.T) {
+	goodMessage := "0022340b000700010002061f"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0022,
+		MessageType:      DownloadSectionResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &DownloadSectionResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 1,
+			Extended:       true,
+		},
+		Result:        me.DeviceBusy,
+		SectionNumber: 0x1f,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestEndSoftwareDownloadRequestDecode(t *testing.T) {
+	//
+	// 8100 55 0a 0007 0001 ff92a226 000f4240 01 0001 00000000000000000000000000000000000000000000000028
+	//
+	goodMessage := "8100550a00070001ff92a226000f424001000100000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeEndSoftwareDownloadRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x8100), omciMsg.TransactionID)
+	assert.Equal(t, EndSoftwareDownloadRequestType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeEndSoftwareDownloadRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*EndSoftwareDownloadRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeEndSoftwareDownloadRequest, request.LayerType())
+	assert.Equal(t, LayerTypeEndSoftwareDownloadRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, uint32(0xff92a226), request.CRC32)
+	assert.Equal(t, uint32(0x000f4240), request.ImageSize)
+	assert.Equal(t, byte(1), request.NumberOfInstances)
+	assert.Equal(t, 1, len(request.ImageInstances))
+	assert.Equal(t, uint16(1), request.ImageInstances[0])
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestEndSoftwareDownloadRequestDecodeExtended(t *testing.T) {
+	//
+	// 8100 55 0a 0007 0001 000b ff92a226 000f4240 01 0001
+	//
+	goodMessage := "8100550b00070001000bff92a226000f4240010001"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeEndSoftwareDownloadRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x8100), omciMsg.TransactionID)
+	assert.Equal(t, EndSoftwareDownloadRequestType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(11), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeEndSoftwareDownloadRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*EndSoftwareDownloadRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeEndSoftwareDownloadRequest, request.LayerType())
+	assert.Equal(t, LayerTypeEndSoftwareDownloadRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, uint32(0xff92a226), request.CRC32)
+	assert.Equal(t, uint32(0x000f4240), request.ImageSize)
+	assert.Equal(t, byte(1), request.NumberOfInstances)
+	assert.Equal(t, 1, len(request.ImageInstances))
+	assert.Equal(t, uint16(1), request.ImageInstances[0])
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestEndSoftwareDownloadRequestSerialize(t *testing.T) {
+	// 8100 55 0a 0007 0001 ff92a226 000f4240 01 0001 00000000000000000000000000000000000000000000000028
+	goodMessage := "8100550a00070001ff92a226000f424001000100000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x8100,
+		MessageType:   EndSoftwareDownloadRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &EndSoftwareDownloadRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 0x0001, // Default is zero, here we want image 1
+		},
+		CRC32:             0xff92a226,
+		ImageSize:         1000000,
+		NumberOfInstances: 1,
+		ImageInstances:    []uint16{1},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestEndSoftwareDownloadRequestZeroTICSerialize(t *testing.T) {
+	// 8100 55 0a 0007 0001 ff92a226 000f4240 01 0001 00000000000000000000000000000000000000000000000028
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   EndSoftwareDownloadRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &EndSoftwareDownloadRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 0x0001, // Default is zero, here we want image 1
+		},
+		CRC32:             0xff92a226,
+		ImageSize:         1000000,
+		NumberOfInstances: 1,
+		ImageInstances:    []uint16{1},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestEndSoftwareDownloadRequestSerializeExtended(t *testing.T) {
+	goodMessage := "8100550b00070001000bff92a226000f4240010001"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x8100,
+		MessageType:      EndSoftwareDownloadRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &EndSoftwareDownloadRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 0x0001, // Default is zero, here we want image 1
+			Extended:       true,
+		},
+		CRC32:             0xff92a226,
+		ImageSize:         1000000,
+		NumberOfInstances: 1,
+		ImageInstances:    []uint16{1},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestEndSoftwareDownloadResponseDecode(t *testing.T) {
+	// 8123 35 0a 0007 0001 06 0000000000000000000000000000000000000000000000000000000000000000000028
+	goodMessage := "8123350a00070001060000000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeEndSoftwareDownloadResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x8123), omciMsg.TransactionID)
+	assert.Equal(t, EndSoftwareDownloadResponseType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeEndSoftwareDownloadResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*EndSoftwareDownloadResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeEndSoftwareDownloadResponse, response.LayerType())
+	assert.Equal(t, LayerTypeEndSoftwareDownloadResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, me.DeviceBusy, response.Result)
+	assert.Equal(t, byte(0), response.NumberOfInstances)
+	assert.Nil(t, response.MeResults)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestEndSoftwareDownloadResponseDecodeExtended(t *testing.T) {
+	goodMessage := "8123350b0007000100020600"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeEndSoftwareDownloadResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x8123), omciMsg.TransactionID)
+	assert.Equal(t, EndSoftwareDownloadResponseType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(2), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeEndSoftwareDownloadResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*EndSoftwareDownloadResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeEndSoftwareDownloadResponse, response.LayerType())
+	assert.Equal(t, LayerTypeEndSoftwareDownloadResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, me.DeviceBusy, response.Result)
+	assert.Equal(t, byte(0), response.NumberOfInstances)
+	assert.Nil(t, response.MeResults)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestEndSoftwareDownloadResponseSerialize(t *testing.T) {
+	goodMessage := "8456350a00070000010000000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x8456,
+		MessageType:   EndSoftwareDownloadResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &EndSoftwareDownloadResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass: me.SoftwareImageClassID,
+			// Default is zero
+		},
+		Result:            me.ProcessingError,
+		NumberOfInstances: 0,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestEndSoftwareDownloadResponseZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   EndSoftwareDownloadResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &EndSoftwareDownloadResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass: me.SoftwareImageClassID,
+			// Default is zero
+		},
+		Result:            me.ProcessingError,
+		NumberOfInstances: 0,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestEndSoftwareDownloadResponseSerializeExtended(t *testing.T) {
+	goodMessage := "8456350b0007000100020100"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x8456,
+		MessageType:      EndSoftwareDownloadResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &EndSoftwareDownloadResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 1,
+			// Default is zero
+			Extended: true,
+		},
+		Result:            me.ProcessingError,
+		NumberOfInstances: 0,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestActivateSoftwareRequestDecode(t *testing.T) {
+	goodMessage := "0009560a00070001020000000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, uint16(9), omciMsg.TransactionID)
+	assert.Equal(t, ActivateSoftwareRequestType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeActivateSoftwareRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*ActivateSoftwareRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, uint8(2), request.ActivateFlags)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestActivateSoftwareRequestDecodeExtended(t *testing.T) {
+	goodMessage := "0009560b00070001000102"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, uint16(9), omciMsg.TransactionID)
+	assert.Equal(t, ActivateSoftwareRequestType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(1), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeActivateSoftwareRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*ActivateSoftwareRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, uint8(2), request.ActivateFlags)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestActivateSoftwareRequestSerialize(t *testing.T) {
+	goodMessage := "0009560b00070001000102"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x09,
+		MessageType:      ActivateSoftwareRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &ActivateSoftwareRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 1,
+			Extended:       true,
+		},
+		ActivateFlags: 2,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestActivateSoftwareRequestZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID:    0x0,
+		MessageType:      ActivateSoftwareRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &ActivateSoftwareRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 1,
+			Extended:       true,
+		},
+		ActivateFlags: 2,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestActivateSoftwareRequestSerializeExtended(t *testing.T) {
+	goodMessage := "0009560b00070001000102"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x09,
+		MessageType:      ActivateSoftwareRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &ActivateSoftwareRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 1,
+			Extended:       true,
+		},
+		ActivateFlags: 2,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestActivateSoftwareResponseDecode(t *testing.T) {
+	goodMessage := "0009360a00070001060000000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, omciMsg.TransactionID, uint16(9))
+	assert.Equal(t, omciMsg.MessageType, ActivateSoftwareResponseType)
+	assert.Equal(t, omciMsg.DeviceIdentifier, BaselineIdent)
+	assert.Equal(t, omciMsg.Length, uint16(40))
+
+	msgLayer := packet.Layer(LayerTypeActivateSoftwareResponse)
+
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*ActivateSoftwareResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, me.DeviceBusy, response.Result)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestActivateSoftwareResponseDecodeExtended(t *testing.T) {
+	goodMessage := "0009360b00070001000106"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.Equal(t, uint16(9), omciMsg.TransactionID)
+	assert.Equal(t, ActivateSoftwareResponseType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(1), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeActivateSoftwareResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*ActivateSoftwareResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, me.DeviceBusy, response.Result)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestActivateSoftwareResponseSerialize(t *testing.T) {
+	goodMessage := "0009360a00070001060000000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x09,
+		MessageType:   ActivateSoftwareResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &ActivateSoftwareResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 1,
+		},
+		Result: me.DeviceBusy,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestActivateSoftwareResponseZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   ActivateSoftwareResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &ActivateSoftwareResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 1,
+		},
+		Result: me.DeviceBusy,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestActivateSoftwareResponseSerializeExtended(t *testing.T) {
+	goodMessage := "0009360b00070001000106"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x09,
+		MessageType:      ActivateSoftwareResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &ActivateSoftwareResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 1,
+			Extended:       true,
+		},
+		Result: me.DeviceBusy,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestCommitSoftwareRequestDecode(t *testing.T) {
+	goodMessage := "0011570a00070001000000000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeCommitSoftwareRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x11), omciMsg.TransactionID)
+	assert.Equal(t, CommitSoftwareRequestType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeCommitSoftwareRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*CommitSoftwareRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeCommitSoftwareRequest, request.LayerType())
+	assert.Equal(t, LayerTypeCommitSoftwareRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, uint16(1), request.MeBasePacket.EntityInstance)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestCommitSoftwareRequestDecodeExtended(t *testing.T) {
+	goodMessage := "0011570b000700010000"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeCommitSoftwareRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x11), omciMsg.TransactionID)
+	assert.Equal(t, CommitSoftwareRequestType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(0), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeCommitSoftwareRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*CommitSoftwareRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeCommitSoftwareRequest, request.LayerType())
+	assert.Equal(t, LayerTypeCommitSoftwareRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, uint16(1), request.MeBasePacket.EntityInstance)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestCommitSoftwareRequestSerialize(t *testing.T) {
+	goodMessage := "0044570a00070001000000000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x44,
+		MessageType:   CommitSoftwareRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &CommitSoftwareRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 1, // Default Instance ID is 0
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestCommitSoftwareRequestZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   CommitSoftwareRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &CommitSoftwareRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 1, // Default Instance ID is 0
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestCommitSoftwareRequestSerializeExtended(t *testing.T) {
+	goodMessage := "0011570b000700010000"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x11,
+		MessageType:      CommitSoftwareRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &CommitSoftwareRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 1, // Default Instance ID is 0
+			Extended:       true,
+		},
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestCommitSoftwareResponseDecode(t *testing.T) {
+	goodMessage := "00aa370a00070001060000000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeCommitSoftwareResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0xaa), omciMsg.TransactionID)
+	assert.Equal(t, CommitSoftwareResponseType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeCommitSoftwareResponse)
+
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*CommitSoftwareResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeCommitSoftwareResponse, response.LayerType())
+	assert.Equal(t, LayerTypeCommitSoftwareResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, uint16(1), response.MeBasePacket.EntityInstance)
+	assert.Equal(t, me.DeviceBusy, response.Result)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestCommitSoftwareResponseDecodeExtended(t *testing.T) {
+	goodMessage := "00aa370b00070001000106"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeCommitSoftwareResponse, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0xaa), omciMsg.TransactionID)
+	assert.Equal(t, CommitSoftwareResponseType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(1), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeCommitSoftwareResponse)
+
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*CommitSoftwareResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeCommitSoftwareResponse, response.LayerType())
+	assert.Equal(t, LayerTypeCommitSoftwareResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, uint16(1), response.MeBasePacket.EntityInstance)
+	assert.Equal(t, me.DeviceBusy, response.Result)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestCommitSoftwareResponseSerialize(t *testing.T) {
+	goodMessage := "8001370a00070001060000000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x8001,
+		MessageType:   CommitSoftwareResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &CommitSoftwareResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 1, // Default Instance ID is 0
+		},
+		Result: me.DeviceBusy,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestCommitSoftwareResponseZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   CommitSoftwareResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &CommitSoftwareResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 1, // Default Instance ID is 0
+		},
+		Result: me.DeviceBusy,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestCommitSoftwareResponseSerializeExtended(t *testing.T) {
+	goodMessage := "8001370b00070001000106"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x8001,
+		MessageType:      CommitSoftwareResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &CommitSoftwareResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: 1, // Default Instance ID is 0
+			Extended:       true,
+		},
+		Result: me.DeviceBusy,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
diff --git a/synctime.go b/synctime.go
new file mode 100644
index 0000000..7e7cad0
--- /dev/null
+++ b/synctime.go
@@ -0,0 +1,314 @@
+/*
+ * 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"
+	"github.com/google/gopacket"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+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)
+}
+
+// LayerType returns LayerTypeSynchronizeTimeRequest
+func (omci *SynchronizeTimeRequest) LayerType() gopacket.LayerType {
+	return LayerTypeSynchronizeTimeRequest
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *SynchronizeTimeRequest) CanDecode() gopacket.LayerClass {
+	return LayerTypeSynchronizeTimeRequest
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *SynchronizeTimeRequest) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	getDateAndTime := true
+	var offset, hdrSize int
+	if omci.Extended {
+		offset = 6
+		hdrSize = offset + 7
+		// Extended format allows for the OLT to support not setting the date and
+		// time (not present in the message)
+		// TODO: There is not a way to indicate this to the user at this time, currently
+		//       all date/time fields will be zero
+		if len(data) < offset {
+			p.SetTruncated()
+			return errors.New("frame too small")
+		}
+		if len(data) < hdrSize {
+			getDateAndTime = false
+			hdrSize = len(data)
+		}
+	} else {
+		offset = 4
+		hdrSize := offset + 7
+		if len(data) < hdrSize {
+			p.SetTruncated()
+			return errors.New("frame too small")
+		}
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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")
+	}
+
+	if getDateAndTime {
+		omci.Year = binary.BigEndian.Uint16(data[offset:])
+		omci.Month = data[offset+2]
+		omci.Day = data[offset+3]
+		omci.Hour = data[offset+4]
+		omci.Minute = data[offset+5]
+		omci.Second = data[offset+6]
+	}
+	return nil
+}
+
+func decodeSynchronizeTimeRequest(data []byte, p gopacket.PacketBuilder) error {
+	omci := &SynchronizeTimeRequest{}
+	omci.MsgLayerType = LayerTypeSynchronizeTimeRequest
+	return decodingLayerDecoder(omci, data, p)
+}
+
+func decodeSynchronizeTimeRequestExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &SynchronizeTimeRequest{}
+	omci.MsgLayerType = LayerTypeSynchronizeTimeRequest
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Synchronize Time Request message
+func (omci *SynchronizeTimeRequest) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	var offset, length int
+	if omci.Extended {
+		// TODO: Extended format allows for the OLT to support not setting the date and
+		//       time (not present in the message). This needs to be supported in a future
+		//       version of the software.
+		offset = 2
+		length = 7
+	} else {
+		offset = 0
+		length = 7
+	}
+	bytes, err := b.AppendBytes(offset + length)
+	if err != nil {
+		return err
+	}
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, uint16(length))
+	}
+	binary.BigEndian.PutUint16(bytes[offset:], omci.Year)
+	if length > 0 {
+		bytes[offset+2] = omci.Month
+		bytes[offset+3] = omci.Day
+		bytes[offset+4] = omci.Hour
+		bytes[offset+5] = omci.Minute
+		bytes[offset+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)
+}
+
+// LayerType returns LayerTypeSynchronizeTimeResponse
+func (omci *SynchronizeTimeResponse) LayerType() gopacket.LayerType {
+	return LayerTypeSynchronizeTimeResponse
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *SynchronizeTimeResponse) CanDecode() gopacket.LayerClass {
+	return LayerTypeSynchronizeTimeResponse
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *SynchronizeTimeResponse) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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
+	var hdrSize, offset int
+	if omci.Extended {
+		offset = 6
+		hdrSize = offset + 1
+		// TODO: Extended message set allows for the optional encoding of the of the
+		//       12th octet (success results) even if the result code is not 0/success.
+		//       This functionality is not currently supported.
+	} else {
+		offset = 4
+		hdrSize = offset + 2
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, hdrSize)
+	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[offset])
+	if omci.Result > me.DeviceBusy {
+		msg := fmt.Sprintf("invalid results code: %v, must be 0..6", omci.Result)
+		return errors.New(msg)
+	}
+	if omci.Result == me.Success && len(data) > offset+1 {
+		omci.SuccessResults = data[offset+1]
+	} else if omci.Extended && len(data) > offset+1 {
+		omci.SuccessResults = data[offset+1]
+	}
+	return nil
+}
+
+func decodeSynchronizeTimeResponse(data []byte, p gopacket.PacketBuilder) error {
+	omci := &SynchronizeTimeResponse{}
+	omci.MsgLayerType = LayerTypeSynchronizeTimeResponse
+	return decodingLayerDecoder(omci, data, p)
+}
+
+func decodeSynchronizeTimeResponseExtended(data []byte, p gopacket.PacketBuilder) error {
+	omci := &SynchronizeTimeResponse{}
+	omci.MsgLayerType = LayerTypeSynchronizeTimeResponse
+	omci.Extended = true
+	return decodingLayerDecoder(omci, data, p)
+}
+
+// SerializeTo provides serialization of an Synchronize Time Response message
+func (omci *SynchronizeTimeResponse) SerializeTo(b gopacket.SerializeBuffer, _ 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")
+	}
+	var offset int
+	if omci.Extended {
+		offset = 2
+	} else {
+		offset = 0
+	}
+	numBytes := 2
+	if omci.Result != me.Success {
+		// TODO: Extended message set allows for the optional encoding of the of the
+		//       12th octet (success results) even if the result code is not 0/success.
+		//       This functionality is not currently supported
+		numBytes = 1
+	}
+	bytes, err := b.AppendBytes(offset + numBytes)
+	if err != nil {
+		return err
+	}
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, uint16(numBytes))
+	}
+	bytes[offset] = uint8(omci.Result)
+	if omci.Result == me.Success {
+		// TODO: Extended message set allows for the optional encoding of the of the
+		//       12th octet (success results) even if the result code is not 0/success.
+		//       This functionality is not currently supported
+		bytes[offset+1] = omci.SuccessResults
+	}
+	return nil
+}
diff --git a/synctime_test.go b/synctime_test.go
new file mode 100644
index 0000000..cf7e99f
--- /dev/null
+++ b/synctime_test.go
@@ -0,0 +1,363 @@
+/*
+ * 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_test
+
+import (
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/stretchr/testify/assert"
+	"strings"
+	"testing"
+)
+
+func TestSynchronizeTimeRequestDecode(t *testing.T) {
+	goodMessage := "0109580a0100000007e20c0101301b0000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeSynchronizeTimeRequest, omciMsg.NextLayerType())
+	assert.Equal(t, SynchronizeTimeRequestType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeSynchronizeTimeRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*SynchronizeTimeRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeSynchronizeTimeRequest, request.LayerType())
+	assert.Equal(t, LayerTypeSynchronizeTimeRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, uint16(2018), request.Year)
+	assert.Equal(t, uint8(12), request.Month)
+	assert.Equal(t, uint8(1), request.Day)
+	assert.Equal(t, uint8(01), request.Hour)
+	assert.Equal(t, uint8(48), request.Minute)
+	assert.Equal(t, uint8(27), request.Second)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestSynchronizeTimeRequestSerialize(t *testing.T) {
+	goodMessage := "0109580a0100000007e20c0101301b0000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x0109,
+		MessageType:   SynchronizeTimeRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &SynchronizeTimeRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass: me.OnuGClassID,
+			// Default Instance ID is 0
+		},
+		Year:   uint16(2018),
+		Month:  uint8(12),
+		Day:    uint8(1),
+		Hour:   uint8(01),
+		Minute: uint8(48),
+		Second: uint8(27),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestSynchronizeTimeRequestZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   SynchronizeTimeRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &SynchronizeTimeRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass: me.OnuGClassID,
+			// Default Instance ID is 0
+		},
+		Year:   uint16(2018),
+		Month:  uint8(12),
+		Day:    uint8(1),
+		Hour:   uint8(01),
+		Minute: uint8(48),
+		Second: uint8(27),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestSynchronizeTimeResponseDecode(t *testing.T) {
+	goodMessage := "0109380a01000000000000000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeSynchronizeTimeResponse, omciMsg.NextLayerType())
+	assert.Equal(t, SynchronizeTimeResponseType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeSynchronizeTimeResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*SynchronizeTimeResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeSynchronizeTimeResponse, response.LayerType())
+	assert.Equal(t, LayerTypeSynchronizeTimeResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestSynchronizeTimeResponseSerialize(t *testing.T) {
+	goodMessage := "0109380a01000000000000000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x0109,
+		MessageType:   SynchronizeTimeResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &SynchronizeTimeResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuGClassID,
+			EntityInstance: uint16(0),
+		},
+		Result:         me.Success,
+		SuccessResults: uint8(0),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestSynchronizeTimeResponseZeroTICSerialize(t *testing.T) {
+	omciLayer := &OMCI{
+		TransactionID: 0x0,
+		MessageType:   SynchronizeTimeResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &SynchronizeTimeResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuGClassID,
+			EntityInstance: uint16(0),
+		},
+		Result:         me.Success,
+		SuccessResults: uint8(0),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.Error(t, err)
+}
+
+func TestExtendedSynchronizeTimeRequestDecode(t *testing.T) {
+	goodMessage := "0109580b01000000000707e20c0101301b"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeSynchronizeTimeRequest, omciMsg.NextLayerType())
+	assert.Equal(t, SynchronizeTimeRequestType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(7), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeSynchronizeTimeRequest)
+	assert.NotNil(t, msgLayer)
+
+	request, ok2 := msgLayer.(*SynchronizeTimeRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, request)
+	assert.Equal(t, LayerTypeSynchronizeTimeRequest, request.LayerType())
+	assert.Equal(t, LayerTypeSynchronizeTimeRequest, request.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, request.NextLayerType())
+	assert.Equal(t, uint16(2018), request.Year)
+	assert.Equal(t, uint8(12), request.Month)
+	assert.Equal(t, uint8(1), request.Day)
+	assert.Equal(t, uint8(01), request.Hour)
+	assert.Equal(t, uint8(48), request.Minute)
+	assert.Equal(t, uint8(27), request.Second)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedSynchronizeTimeRequestSerialize(t *testing.T) {
+	goodMessage := "0109580b01000000000707e20c0101301b"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0109,
+		MessageType:      SynchronizeTimeRequestType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &SynchronizeTimeRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass: me.OnuGClassID,
+			Extended:    true,
+		},
+		Year:   uint16(2018),
+		Month:  uint8(12),
+		Day:    uint8(1),
+		Hour:   uint8(01),
+		Minute: uint8(48),
+		Second: uint8(27),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestExtendedSynchronizeTimeResponseDecode(t *testing.T) {
+	goodMessage := "0109380b0100000000020001"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeSynchronizeTimeResponse, omciMsg.NextLayerType())
+	assert.Equal(t, SynchronizeTimeResponseType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(2), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeSynchronizeTimeResponse)
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*SynchronizeTimeResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeSynchronizeTimeResponse, response.LayerType())
+	assert.Equal(t, LayerTypeSynchronizeTimeResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, me.Success, response.Result)
+	assert.Equal(t, uint8(1), response.SuccessResults)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedSynchronizeTimeResponseSerialize(t *testing.T) {
+	goodMessage := "0109380b0100000000020001"
+
+	omciLayer := &OMCI{
+		TransactionID:    0x0109,
+		MessageType:      SynchronizeTimeResponseType,
+		DeviceIdentifier: ExtendedIdent,
+	}
+	request := &SynchronizeTimeResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass: me.OnuGClassID,
+			Extended:    true,
+		},
+		Result:         me.Success,
+		SuccessResults: uint8(1),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
diff --git a/test.go b/test.go
new file mode 100644
index 0000000..00ea602
--- /dev/null
+++ b/test.go
@@ -0,0 +1,556 @@
+/*
+ * 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"
+	"github.com/google/gopacket"
+	me "github.com/opencord/omci-lib-go/generated"
+)
+
+func decodeTestRequest(data []byte, p gopacket.PacketBuilder) error {
+	// Peek at Managed Entity Type
+	if len(data) < 8 {
+		p.SetTruncated()
+		return errors.New("frame too small")
+	}
+	classID := binary.BigEndian.Uint16(data)
+
+	// Is it a Managed Entity class we support customized decode of?
+	switch me.ClassID(classID) {
+	default:
+		omci := &TestRequest{}
+		omci.MsgLayerType = LayerTypeTestRequest
+		return decodingLayerDecoder(omci, data, p)
+
+	case me.AniGClassID, me.ReAniGClassID, me.PhysicalPathTerminationPointReUniClassID,
+		me.ReUpstreamAmplifierClassID, me.ReDownstreamAmplifierClassID:
+		omci := &OpticalLineSupervisionTestRequest{}
+		omci.MsgLayerType = LayerTypeTestRequest
+		return decodingLayerDecoder(omci, data, p)
+	}
+}
+
+// TestRequest message
+type TestRequest struct {
+	MeBasePacket
+	Payload []byte
+}
+
+func (omci *TestRequest) String() string {
+	return fmt.Sprintf("%v, Request: %v octets", omci.MeBasePacket.String(), len(omci.Payload))
+}
+
+// LayerType returns LayerTypeTestRequest
+func (omci *TestRequest) LayerType() gopacket.LayerType {
+	return LayerTypeTestRequest
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *TestRequest) CanDecode() gopacket.LayerClass {
+	return LayerTypeTestRequest
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *TestRequest) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+func (omci *TestRequest) TestRequest() []byte {
+	return omci.Payload
+}
+
+// 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, 4)
+	if err != nil {
+		return err
+	}
+
+	omci.Payload = make([]byte, MaxTestRequestLength)
+	copy(omci.Payload, omci.MeBasePacket.Payload)
+	return nil
+}
+
+// SerializeTo provides serialization of an Test Request message
+func (omci *TestRequest) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets, 10
+	err := omci.MeBasePacket.SerializeTo(b)
+	if err != nil {
+		return err
+	}
+	if omci.Payload == nil {
+		return errors.New("test results payload is missing")
+	}
+
+	if len(omci.Payload) > MaxTestRequestLength {
+		msg := fmt.Sprintf("Invalid Test Request payload size. Received %v bytes, expected %v",
+			len(omci.Payload), MaxTestRequestLength)
+		return errors.New(msg)
+	}
+	bytes, err := b.AppendBytes(len(omci.Payload))
+	if err != nil {
+		return err
+	}
+
+	copy(bytes, omci.Payload)
+	return nil
+}
+
+type OpticalLineSupervisionTestRequest struct {
+	MeBasePacket
+	SelectTest               uint8  // Bitfield
+	GeneralPurposeBuffer     uint16 // Pointer to General Purpose Buffer ME
+	VendorSpecificParameters uint16 // Pointer to Octet String ME
+}
+
+func (omci *OpticalLineSupervisionTestRequest) String() string {
+	return fmt.Sprintf("Optical Line Supervision Test Result: SelectTest: %#x, Buffer: %#x, Params: %#x",
+		omci.SelectTest, omci.GeneralPurposeBuffer, omci.VendorSpecificParameters)
+}
+
+// LayerType returns LayerTypeTestRequest
+func (omci *OpticalLineSupervisionTestRequest) LayerType() gopacket.LayerType {
+	return LayerTypeTestRequest
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *OpticalLineSupervisionTestRequest) CanDecode() gopacket.LayerClass {
+	return LayerTypeTestRequest
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *OpticalLineSupervisionTestRequest) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+func (omci *OpticalLineSupervisionTestRequest) TestRequest() []byte {
+	return omci.Payload
+}
+
+// DecodeFromBytes decodes the given bytes of a Test Result Notification into this layer
+func (omci *OpticalLineSupervisionTestRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, 4+5)
+	if err != nil {
+		return err
+	}
+
+	omci.SelectTest = data[4]
+	omci.GeneralPurposeBuffer = binary.BigEndian.Uint16(data[5:])
+	omci.VendorSpecificParameters = binary.BigEndian.Uint16(data[7:])
+	return nil
+}
+
+// SerializeTo provides serialization of an Test Result notification message
+func (omci *OpticalLineSupervisionTestRequest) SerializeTo(b gopacket.SerializeBuffer, _ 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(8)
+	if err != nil {
+		return err
+	}
+
+	bytes[0] = omci.SelectTest
+	binary.BigEndian.PutUint16(bytes[1:], omci.GeneralPurposeBuffer)
+	binary.BigEndian.PutUint16(bytes[3:], omci.VendorSpecificParameters)
+	return nil
+}
+
+// TestResponse message
+type TestResponse struct {
+	MeBasePacket
+	Result me.Results
+}
+
+func (omci *TestResponse) String() string {
+	return fmt.Sprintf("%v, Results: %d (%v)", omci.MeBasePacket.String(), omci.Result, omci.Result)
+}
+
+// LayerType returns LayerTypeTestResponse
+func (omci *TestResponse) LayerType() gopacket.LayerType {
+	return LayerTypeTestResponse
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *TestResponse) CanDecode() gopacket.LayerClass {
+	return LayerTypeTestResponse
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *TestResponse) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// 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, 4+1)
+	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 Test requests
+	if !me.SupportsMsgType(meDefinition, me.Test) {
+		return me.NewProcessingError("managed entity does not support Test Message-Type")
+	}
+	omci.Result = me.Results(data[4])
+	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, _ 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.Test) {
+		return me.NewProcessingError("managed entity does not support the Test Message-Type")
+	}
+	bytes, err := b.AppendBytes(1)
+	if err != nil {
+		return err
+	}
+	bytes[0] = byte(omci.Result)
+
+	if omci.Result > me.DeviceBusy {
+		msg := fmt.Sprintf("invalid results code: %v, must be 0..6", omci.Result)
+		return errors.New(msg)
+	}
+	return nil
+}
+
+func decodeTestResult(data []byte, p gopacket.PacketBuilder) error {
+	// Peek at Managed Entity Type
+	if len(data) < 8 {
+		p.SetTruncated()
+		return errors.New("frame too small")
+	}
+	classID := binary.BigEndian.Uint16(data)
+
+	// Is it a Managed Entity class we support customized decode of?
+	switch me.ClassID(classID) {
+	default:
+		omci := &TestResultNotification{}
+		omci.MsgLayerType = LayerTypeTestResult
+		return decodingLayerDecoder(omci, data, p)
+
+	case me.AniGClassID, me.ReAniGClassID, me.PhysicalPathTerminationPointReUniClassID,
+		me.ReUpstreamAmplifierClassID, me.ReDownstreamAmplifierClassID:
+		omci := &OpticalLineSupervisionTestResult{}
+		omci.MsgLayerType = LayerTypeTestResult
+		return decodingLayerDecoder(omci, data, p)
+	}
+}
+
+func decodeTestResultExtended(data []byte, p gopacket.PacketBuilder) error {
+	// Peek at Managed Entity Type
+	if len(data) < 8 {
+		p.SetTruncated()
+		return errors.New("frame too small")
+	}
+	classID := binary.BigEndian.Uint16(data)
+
+	// Is it a Managed Entity class we support customized decode of?
+	switch me.ClassID(classID) {
+	default:
+		omci := &TestResultNotification{}
+		omci.MsgLayerType = LayerTypeTestResult
+		omci.Extended = true
+		return decodingLayerDecoder(omci, data, p)
+
+	case me.AniGClassID, me.ReAniGClassID, me.PhysicalPathTerminationPointReUniClassID,
+		me.ReUpstreamAmplifierClassID, me.ReDownstreamAmplifierClassID:
+		omci := &OpticalLineSupervisionTestResult{}
+		omci.MsgLayerType = LayerTypeTestResult
+		omci.Extended = true
+		return decodingLayerDecoder(omci, data, p)
+	}
+}
+
+type TestResultNotification struct {
+	MeBasePacket
+	Payload []byte
+}
+
+func (omci *TestResultNotification) TestResults() []byte {
+	return omci.Payload
+}
+
+func (omci *TestResultNotification) String() string {
+	return fmt.Sprintf("%v, Payload: %v octets", omci.MeBasePacket.String(), len(omci.Payload))
+}
+
+// LayerType returns LayerTypeTestResult
+func (omci *TestResultNotification) LayerType() gopacket.LayerType {
+	return LayerTypeTestResult
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *TestResultNotification) CanDecode() gopacket.LayerClass {
+	return LayerTypeTestResult
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *TestResultNotification) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+// DecodeFromBytes decodes the given bytes of a Test Result Notification into this layer
+func (omci *TestResultNotification) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	payloadOffset := 4
+	if omci.Extended {
+		payloadOffset = 6
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, payloadOffset)
+	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 Test requests
+	if !me.SupportsMsgType(meDefinition, me.Test) {
+		return me.NewProcessingError("managed entity does not support Test Message-Type")
+	}
+	if omci.Extended {
+		if len(data) < 6 {
+			p.SetTruncated()
+			return errors.New("frame too small")
+		}
+		length := binary.BigEndian.Uint16(data[4:])
+		if len(data) < 6+int(length) {
+			p.SetTruncated()
+			return errors.New("frame too small")
+		}
+		omci.Payload = make([]byte, length)
+		copy(omci.Payload, data[6:])
+	} else {
+		omci.Payload = make([]byte, MaxTestResultsLength)
+		copy(omci.Payload, omci.MeBasePacket.Payload)
+	}
+	return nil
+}
+
+// SerializeTo provides serialization of an Test Result notification message
+func (omci *TestResultNotification) SerializeTo(b gopacket.SerializeBuffer, _ gopacket.SerializeOptions) error {
+	// Basic (common) OMCI Header is 8 octets
+	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 Test requests
+	if !me.SupportsMsgType(meDefinition, me.Test) {
+		return me.NewProcessingError("managed entity does not support Test Message-Type")
+	}
+	if omci.Payload == nil {
+		return errors.New("test results payload is missing")
+	}
+
+	payloadOffset := 0
+	maxSize := MaxTestResultsLength
+
+	if omci.Extended {
+		payloadOffset = 2
+		maxSize = MaxExtendedLength - 10 - 4
+	}
+	if len(omci.Payload) > maxSize {
+		msg := fmt.Sprintf("Invalid Test Results payload size. Received %v bytes, max expected %v",
+			len(omci.Payload), maxSize)
+		return errors.New(msg)
+	}
+	bytes, err := b.AppendBytes(len(omci.Payload) + payloadOffset)
+	if err != nil {
+		return err
+	}
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, uint16(len(omci.Payload)))
+	}
+	copy(bytes[payloadOffset:], omci.Payload)
+	return nil
+}
+
+// OpticalLineSupervisionTestResult provides a Optical Specific test results
+// message decode for the associated Managed Entities
+type OpticalLineSupervisionTestResult struct {
+	MeBasePacket
+	PowerFeedVoltageType     uint8  // Type = 1
+	PowerFeedVoltage         uint16 // value
+	ReceivedOpticalPowerType uint8  // Type = 3
+	ReceivedOpticalPower     uint16 // value
+	MeanOpticalLaunchType    uint8  // Type = 5
+	MeanOpticalLaunch        uint16 // value
+	LaserBiasCurrentType     uint8  // Type = 9
+	LaserBiasCurrent         uint16 // value
+	TemperatureType          uint8  // Type = 12
+	Temperature              uint16 // value
+
+	GeneralPurposeBuffer uint16 // Pointer to General Purpose Buffer ME
+}
+
+func (omci *OpticalLineSupervisionTestResult) String() string {
+	return fmt.Sprintf("Optical Line Supervision Test Result")
+}
+
+// LayerType returns LayerTypeTestResult
+func (omci *OpticalLineSupervisionTestResult) LayerType() gopacket.LayerType {
+	return LayerTypeTestResult
+}
+
+// CanDecode returns the set of layer types that this DecodingLayer can decode
+func (omci *OpticalLineSupervisionTestResult) CanDecode() gopacket.LayerClass {
+	return LayerTypeTestResult
+}
+
+// NextLayerType returns the layer type contained by this DecodingLayer.
+func (omci *OpticalLineSupervisionTestResult) NextLayerType() gopacket.LayerType {
+	return gopacket.LayerTypePayload
+}
+
+func (omci *OpticalLineSupervisionTestResult) TestResults() []byte {
+	return omci.MeBasePacket.Payload
+}
+
+// DecodeFromBytes decodes the given bytes of a Test Result Notification into this layer
+func (omci *OpticalLineSupervisionTestResult) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
+	// Common ClassID/EntityID decode in msgBase
+	payloadOffset := 4
+	if omci.Extended {
+		payloadOffset = 6
+	}
+	err := omci.MeBasePacket.DecodeFromBytes(data, p, payloadOffset+17)
+	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 Test requests
+	if !me.SupportsMsgType(meDefinition, me.Test) {
+		return me.NewProcessingError("managed entity does not support Test Message-Type")
+	}
+	// Note: Unsupported tests will have a type = 0 and the value should be zero
+	//       as well, but that constraint is not enforced at this time.
+	// Type = 1
+	omci.PowerFeedVoltageType = data[payloadOffset]
+	omci.PowerFeedVoltage = binary.BigEndian.Uint16(data[payloadOffset+1:])
+
+	// Type = 3
+	omci.ReceivedOpticalPowerType = data[payloadOffset+3]
+	omci.ReceivedOpticalPower = binary.BigEndian.Uint16(data[payloadOffset+4:])
+
+	// Type = 5
+	omci.MeanOpticalLaunchType = data[payloadOffset+6]
+	omci.MeanOpticalLaunch = binary.BigEndian.Uint16(data[payloadOffset+7:])
+
+	// Type = 9
+	omci.LaserBiasCurrentType = data[payloadOffset+9]
+	omci.LaserBiasCurrent = binary.BigEndian.Uint16(data[payloadOffset+10:])
+
+	// Type = 12
+	omci.TemperatureType = data[payloadOffset+12]
+	omci.Temperature = binary.BigEndian.Uint16(data[payloadOffset+13:])
+
+	omci.GeneralPurposeBuffer = binary.BigEndian.Uint16(data[payloadOffset+15:])
+	return nil
+}
+
+// SerializeTo provides serialization of an Test Result notification message
+func (omci *OpticalLineSupervisionTestResult) SerializeTo(b gopacket.SerializeBuffer, _ 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 Test requests
+	if !me.SupportsMsgType(meDefinition, me.Test) {
+		return me.NewProcessingError("managed entity does not support Test Message-Type")
+	}
+	payloadOffset := 0
+
+	if omci.Extended {
+		payloadOffset = 2
+	}
+	bytes, err := b.AppendBytes(payloadOffset + 17)
+	if err != nil {
+		return err
+	}
+
+	if omci.Extended {
+		binary.BigEndian.PutUint16(bytes, 17)
+	}
+	bytes[payloadOffset] = omci.PowerFeedVoltageType
+	binary.BigEndian.PutUint16(bytes[payloadOffset+1:], omci.PowerFeedVoltage)
+	bytes[payloadOffset+3] = omci.ReceivedOpticalPowerType
+	binary.BigEndian.PutUint16(bytes[payloadOffset+4:], omci.ReceivedOpticalPower)
+	bytes[payloadOffset+6] = omci.MeanOpticalLaunchType
+	binary.BigEndian.PutUint16(bytes[payloadOffset+7:], omci.MeanOpticalLaunch)
+	bytes[payloadOffset+9] = omci.LaserBiasCurrentType
+	binary.BigEndian.PutUint16(bytes[payloadOffset+10:], omci.LaserBiasCurrent)
+	bytes[payloadOffset+12] = omci.TemperatureType
+	binary.BigEndian.PutUint16(bytes[payloadOffset+13:], omci.Temperature)
+	binary.BigEndian.PutUint16(bytes[payloadOffset+15:], omci.GeneralPurposeBuffer)
+	return nil
+}
diff --git a/test_test.go b/test_test.go
new file mode 100644
index 0000000..b387428
--- /dev/null
+++ b/test_test.go
@@ -0,0 +1,691 @@
+/*
+ * 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_test
+
+import (
+	"fmt"
+	"github.com/google/gopacket"
+	. "github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/stretchr/testify/assert"
+	"strings"
+	"testing"
+)
+
+func TestGenericTestResultDecode(t *testing.T) {
+	// ONU-G ME for this test with just made up data
+	payload := "1234567890123456789012345678901234567890123456789012345678901234"
+	goodMessage := "00001b0a01000000" + payload + "00000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeTestResult, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0000), omciMsg.TransactionID)
+	assert.Equal(t, TestResultType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeTestResult)
+	assert.NotNil(t, msgLayer)
+
+	// This is a generic struct since we do not do detailed decode
+	generic, ok2 := msgLayer.(*TestResultNotification)
+	assert.True(t, ok2)
+	assert.NotNil(t, generic)
+	assert.Equal(t, LayerTypeTestResult, generic.LayerType())
+	assert.Equal(t, LayerTypeTestResult, generic.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, generic.NextLayerType())
+	assert.NotNil(t, generic.MeBasePacket.Payload) // Next three all same data
+	assert.NotNil(t, generic.Payload)
+	assert.NotNil(t, generic.TestResults())
+
+	base := generic.MeBasePacket
+	assert.Equal(t, me.OnuGClassID, base.EntityClass)
+	assert.Equal(t, uint16(0), base.EntityInstance)
+
+	// For the generic Test Result, get the payload data which is all the data in
+	// the test notification past the Entity Instance value.
+	payloadData, payloadErr := stringToPacket(payload)
+	assert.NotNil(t, payloadData)
+	assert.NoError(t, payloadErr)
+	assert.Equal(t, payloadData, base.Payload)
+	assert.Equal(t, payloadData, generic.Payload)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestOpticalLineSupervisionTestResultDecode(t *testing.T) {
+	// ANI-G ME for this test with just made up data
+	payload := "010034" + "030067" + "050091" + "090034" + "0c0067" + "8901" + "000000000000000000000000000000"
+	goodMessage := "00001b0a01078001" + payload + "00000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeTestResult, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0000), omciMsg.TransactionID)
+	assert.Equal(t, TestResultType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeTestResult)
+	assert.NotNil(t, msgLayer)
+
+	// This is a optical line test results
+	optical, ok2 := msgLayer.(*OpticalLineSupervisionTestResult)
+	assert.True(t, ok2)
+	assert.NotNil(t, optical)
+	assert.Equal(t, LayerTypeTestResult, optical.LayerType())
+	assert.Equal(t, LayerTypeTestResult, optical.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, optical.NextLayerType())
+
+	// Get the Managed Entity class ID and instance ID from the base packet
+	base := optical.MeBasePacket
+	assert.Equal(t, me.AniGClassID, base.EntityClass)
+	assert.Equal(t, uint16(0x8001), base.EntityInstance)
+
+	assert.Equal(t, uint8(1), optical.PowerFeedVoltageType)
+	assert.Equal(t, uint16(0x34), optical.PowerFeedVoltage)
+
+	assert.Equal(t, uint8(3), optical.ReceivedOpticalPowerType)
+	assert.Equal(t, uint16(0x67), optical.ReceivedOpticalPower)
+
+	assert.Equal(t, uint8(5), optical.MeanOpticalLaunchType)
+	assert.Equal(t, uint16(0x91), optical.MeanOpticalLaunch)
+
+	assert.Equal(t, uint8(9), optical.LaserBiasCurrentType)
+	assert.Equal(t, uint16(0x34), optical.LaserBiasCurrent)
+
+	assert.Equal(t, uint8(12), optical.TemperatureType)
+	assert.Equal(t, uint16(0x67), optical.Temperature)
+
+	assert.Equal(t, uint16(0x8901), optical.GeneralPurposeBuffer)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestGenericTestResultSerialize(t *testing.T) {
+	payload := "1234567891234567890123456789012345678901234567890123456789012345"
+	goodMessage := "00001b0a01000000" + payload + "00000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x0000, // Optional for notifications since TID always 0x0000
+		MessageType:   TestResultType,
+		// DeviceIdentifier: omci.BaselineIdent,    // Optional, defaults to Baseline
+		// Length:           0x28,					// Optional, defaults to 40 octets
+	}
+	data, derr := stringToPacket(payload)
+	assert.NoError(t, derr)
+
+	request := &TestResultNotification{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuGClassID,
+			EntityInstance: uint16(0),
+		},
+		Payload: data,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestGenericTestResultNonZeroTICSerialize(t *testing.T) {
+	payload := "1234567891234567890123456789012345678901234567890123456789012345"
+	goodMessage := "12341b0a01000000" + payload + "00000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x1234,
+		MessageType:   TestResultType,
+		// DeviceIdentifier: omci.BaselineIdent,    // Optional, defaults to Baseline
+		// Length:           0x28,					// Optional, defaults to 40 octets
+	}
+	data, derr := stringToPacket(payload)
+	assert.NoError(t, derr)
+
+	request := &TestResultNotification{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuGClassID,
+			EntityInstance: uint16(0),
+		},
+		Payload: data,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestOpticalLineSupervisionTestResultSerialize(t *testing.T) {
+	// ANI-G ME for this test with just made up data
+	payload := "010034" + "030067" + "050091" + "090034" + "0c0067" + "8901" + "000000000000000000000000000000"
+	goodMessage := "00001b0a01078001" + payload + "00000028"
+
+	omciLayer := &OMCI{
+		// TransactionID: 0x0c,						// Optional for notifications since TID always 0x0000
+		MessageType: TestResultType,
+		// DeviceIdentifier: omci.BaselineIdent,    // Optional, defaults to Baseline
+		// Length:           0x28,					// Optional, defaults to 40 octets
+	}
+	request := &OpticalLineSupervisionTestResult{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.AniGClassID,
+			EntityInstance: uint16(0x8001),
+		},
+		PowerFeedVoltageType:     uint8(1),
+		PowerFeedVoltage:         uint16(0x34),
+		ReceivedOpticalPowerType: uint8(3),
+		ReceivedOpticalPower:     uint16(0x67),
+		MeanOpticalLaunchType:    uint8(5),
+		MeanOpticalLaunch:        uint16(0x91),
+		LaserBiasCurrentType:     uint8(9),
+		LaserBiasCurrent:         uint16(0x34),
+		TemperatureType:          uint8(12),
+		Temperature:              uint16(0x67),
+		GeneralPurposeBuffer:     uint16(0x8901),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestGenericTestRequestDecode(t *testing.T) {
+	// ONU-G ME for this test with just made up data
+	payload := "1234567890523456789012345678901234567890123456789012345678901234"
+	goodMessage := "0123520a01000000" + payload + "00000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeTestRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0123), omciMsg.TransactionID)
+	assert.Equal(t, TestRequestType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeTestRequest)
+	assert.NotNil(t, msgLayer)
+
+	// This is a generic struct since we do not do detailed decode
+	generic, ok2 := msgLayer.(*TestRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, generic)
+	assert.Equal(t, LayerTypeTestRequest, generic.LayerType())
+	assert.Equal(t, LayerTypeTestRequest, generic.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, generic.NextLayerType())
+	assert.NotNil(t, generic.MeBasePacket.Payload) // Next three all same data
+	assert.NotNil(t, generic.Payload)
+	assert.NotNil(t, generic.TestRequest())
+
+	base := generic.MeBasePacket
+	assert.Equal(t, me.OnuGClassID, base.EntityClass)
+	assert.Equal(t, uint16(0), base.EntityInstance)
+
+	// For the generic Test Result, get the payload data which is all the data in
+	// the test notification past the Entity Instance value.
+	payloadData, payloadErr := stringToPacket(payload)
+	assert.NotNil(t, payloadData)
+	assert.NoError(t, payloadErr)
+	assert.Equal(t, payloadData, base.Payload)
+	assert.Equal(t, payloadData, generic.Payload)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestOpticalLineSupervisionTestRequestDecode(t *testing.T) {
+	// ANI-G ME for this test with just made up data
+	payload := "01" + "1234" + "5678" + "000000000000000000000000000000000000000000000000000000"
+	goodMessage := "0ddd520a01078001" + payload + "00000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeTestRequest, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0ddd), omciMsg.TransactionID)
+	assert.Equal(t, TestRequestType, omciMsg.MessageType)
+	assert.Equal(t, BaselineIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeTestRequest)
+	assert.NotNil(t, msgLayer)
+
+	// This is a optical line test results
+	optical, ok2 := msgLayer.(*OpticalLineSupervisionTestRequest)
+	assert.True(t, ok2)
+	assert.NotNil(t, optical)
+	assert.Equal(t, LayerTypeTestRequest, optical.LayerType())
+	assert.Equal(t, LayerTypeTestRequest, optical.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, optical.NextLayerType())
+
+	// Get the Managed Entity class ID and instance ID from the base packet
+	base := optical.MeBasePacket
+	assert.Equal(t, me.AniGClassID, base.EntityClass)
+	assert.Equal(t, uint16(0x8001), base.EntityInstance)
+
+	assert.Equal(t, uint8(1), optical.SelectTest)
+	assert.Equal(t, uint16(0x1234), optical.GeneralPurposeBuffer)
+	assert.Equal(t, uint16(0x5678), optical.VendorSpecificParameters)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestGenericTestRequestSerialize(t *testing.T) {
+	payload := "1234567891234567890123456789012345678901234567890123456789012345"
+	goodMessage := "eeee520a01000000" + payload + "00000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0xeeee,
+		MessageType:   TestRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,    // Optional, defaults to Baseline
+		// Length:           0x28,					// Optional, defaults to 40 octets
+	}
+	data, derr := stringToPacket(payload)
+	assert.NoError(t, derr)
+
+	request := &TestRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuGClassID,
+			EntityInstance: uint16(0),
+		},
+		Payload: data,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestOpticalLineSupervisionTestRequestSerialize(t *testing.T) {
+	// ANI-G ME for this test with just made up data
+	payload := "01" + "1234" + "5678" + "000000000000000000000000000000000000000000000000000000"
+	goodMessage := "bbbb520a01078001" + payload + "00000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0xbbbb,
+		MessageType:   TestRequestType,
+		// DeviceIdentifier: omci.BaselineIdent,    // Optional, defaults to Baseline
+		// Length:           0x28,					// Optional, defaults to 40 octets
+	}
+	request := &OpticalLineSupervisionTestRequest{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.AniGClassID,
+			EntityInstance: uint16(0x8001),
+		},
+		SelectTest:               uint8(1),
+		GeneralPurposeBuffer:     uint16(0x1234),
+		VendorSpecificParameters: uint16(0x5678),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestTestResponseDecode(t *testing.T) {
+	goodMessage := "0001320A01000000000000000000000000000000000000000000000000000000000000000000000000000028"
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeTestResponse, omciMsg.NextLayerType())
+	assert.Equal(t, TestResponseType, omciMsg.MessageType)
+	assert.Equal(t, uint16(40), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeTestResponse)
+
+	assert.NotNil(t, msgLayer)
+
+	response, ok2 := msgLayer.(*TestResponse)
+	assert.True(t, ok2)
+	assert.NotNil(t, response)
+	assert.Equal(t, LayerTypeTestResponse, response.LayerType())
+	assert.Equal(t, LayerTypeTestResponse, response.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, response.NextLayerType())
+	assert.Equal(t, me.OnuGClassID, response.EntityClass)
+	assert.Equal(t, uint16(0), response.EntityInstance)
+	assert.Equal(t, me.Success, response.Result)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestTestResponseSerialize(t *testing.T) {
+	goodMessage := "0001320A01000000000000000000000000000000000000000000000000000000000000000000000000000028"
+
+	omciLayer := &OMCI{
+		TransactionID: 0x01,
+		MessageType:   TestResponseType,
+		// DeviceIdentifier: omci.BaselineIdent,		// Optional, defaults to Baseline
+		// Length:           0x28,						// Optional, defaults to 40 octets
+	}
+	request := &TestResponse{
+		MeBasePacket: MeBasePacket{
+			EntityClass: me.OnuGClassID,
+			// Default Instance ID is 0
+		},
+		Result: me.Success,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestExtendedGenericTestResultDecode(t *testing.T) {
+	// ONU-G ME for this test with just made up data
+	payload := "1234567890123456789012345678901234567890"
+	resultLen := len(payload) / 2
+	goodMessage := "00001b0b01000000" + fmt.Sprintf("%04x", resultLen) + payload
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeTestResult, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0000), omciMsg.TransactionID)
+	assert.Equal(t, TestResultType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, omciMsg.Length, uint16(resultLen))
+
+	msgLayer := packet.Layer(LayerTypeTestResult)
+	assert.NotNil(t, msgLayer)
+
+	// This is a generic struct since we do not do detailed decode
+	generic, ok2 := msgLayer.(*TestResultNotification)
+	assert.True(t, ok2)
+	assert.NotNil(t, generic)
+	assert.Equal(t, LayerTypeTestResult, generic.LayerType())
+	assert.Equal(t, LayerTypeTestResult, generic.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, generic.NextLayerType())
+	assert.NotNil(t, generic.MeBasePacket.Payload) // Next three all same data
+	assert.NotNil(t, generic.Payload)
+	assert.NotNil(t, generic.TestResults())
+
+	base := generic.MeBasePacket
+	assert.Equal(t, me.OnuGClassID, base.EntityClass)
+	assert.Equal(t, uint16(0), base.EntityInstance)
+
+	// For the generic Test Result, get the payload data which is all the data in
+	// the test notification past the Entity Instance value.
+	payloadData, payloadErr := stringToPacket(payload)
+	assert.NotNil(t, payloadData)
+	assert.NoError(t, payloadErr)
+	assert.Equal(t, payloadData, base.Payload)
+	assert.Equal(t, payloadData, generic.Payload)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedOpticalLineSupervisionTestResultDecode(t *testing.T) {
+	// ANI-G ME for this test with just made up data
+	payload := "010034" + "030067" + "050091" + "090034" + "0c0067" + "8901"
+	resultLen := len(payload) / 2
+	goodMessage := "00001b0b01078001" + fmt.Sprintf("%04x", resultLen) + payload
+	data, err := stringToPacket(goodMessage)
+	assert.NoError(t, err)
+
+	packet := gopacket.NewPacket(data, LayerTypeOMCI, gopacket.NoCopy)
+	assert.NotNil(t, packet)
+
+	omciLayer := packet.Layer(LayerTypeOMCI)
+	assert.NotNil(t, omciLayer)
+
+	omciMsg, ok := omciLayer.(*OMCI)
+	assert.True(t, ok)
+	assert.NotNil(t, omciMsg)
+	assert.Equal(t, LayerTypeOMCI, omciMsg.LayerType())
+	assert.Equal(t, LayerTypeOMCI, omciMsg.CanDecode())
+	assert.Equal(t, LayerTypeTestResult, omciMsg.NextLayerType())
+	assert.Equal(t, uint16(0x0000), omciMsg.TransactionID)
+	assert.Equal(t, TestResultType, omciMsg.MessageType)
+	assert.Equal(t, ExtendedIdent, omciMsg.DeviceIdentifier)
+	assert.Equal(t, uint16(resultLen), omciMsg.Length)
+
+	msgLayer := packet.Layer(LayerTypeTestResult)
+	assert.NotNil(t, msgLayer)
+
+	// This is a optical line test results
+	optical, ok2 := msgLayer.(*OpticalLineSupervisionTestResult)
+	assert.True(t, ok2)
+	assert.NotNil(t, optical)
+	assert.Equal(t, LayerTypeTestResult, optical.LayerType())
+	assert.Equal(t, LayerTypeTestResult, optical.CanDecode())
+	assert.Equal(t, gopacket.LayerTypePayload, optical.NextLayerType())
+
+	// Get the Managed Entity class ID and instance ID from the base packet
+	base := optical.MeBasePacket
+	assert.Equal(t, me.AniGClassID, base.EntityClass)
+	assert.Equal(t, uint16(0x8001), base.EntityInstance)
+
+	assert.Equal(t, uint8(1), optical.PowerFeedVoltageType)
+	assert.Equal(t, uint16(0x34), optical.PowerFeedVoltage)
+
+	assert.Equal(t, uint8(3), optical.ReceivedOpticalPowerType)
+	assert.Equal(t, uint16(0x67), optical.ReceivedOpticalPower)
+
+	assert.Equal(t, uint8(5), optical.MeanOpticalLaunchType)
+	assert.Equal(t, uint16(0x91), optical.MeanOpticalLaunch)
+
+	assert.Equal(t, uint8(9), optical.LaserBiasCurrentType)
+	assert.Equal(t, uint16(0x34), optical.LaserBiasCurrent)
+
+	assert.Equal(t, uint8(12), optical.TemperatureType)
+	assert.Equal(t, uint16(0x67), optical.Temperature)
+
+	assert.Equal(t, uint16(0x8901), optical.GeneralPurposeBuffer)
+
+	// Verify string output for message
+	packetString := packet.String()
+	assert.NotZero(t, len(packetString))
+}
+
+func TestExtendedGenericTestResultSerialize(t *testing.T) {
+	payload := "12345678901234567890"
+	resultLen := len(payload) / 2
+	goodMessage := "00001b0b01000000" + fmt.Sprintf("%04x", resultLen) + payload
+
+	omciLayer := &OMCI{
+		// TransactionID: 0x0c,						// Optional for notifications since TID always 0x0000
+		MessageType:      TestResultType,
+		DeviceIdentifier: ExtendedIdent,
+		// Length parameter is optional for Extended message format serialization
+		// and if present it will be overwritten during the serialization with the
+		// actual value.
+	}
+	data, derr := stringToPacket(payload)
+	assert.NoError(t, derr)
+
+	request := &TestResultNotification{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.OnuGClassID,
+			EntityInstance: uint16(0),
+			Extended:       true,
+		},
+		Payload: data,
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}
+
+func TestExtendedOpticalLineSupervisionTestResultSerialize(t *testing.T) {
+	// ANI-G ME for this test with just made up data
+	payload := "010034" + "030067" + "050091" + "090034" + "0c0067" + "8901"
+	resultLen := len(payload) / 2
+	goodMessage := "00001b0b01078001" + fmt.Sprintf("%04x", resultLen) + payload
+
+	omciLayer := &OMCI{
+		// TransactionID: 0x0c,						// Optional for notifications since TID always 0x0000
+		MessageType:      TestResultType,
+		DeviceIdentifier: ExtendedIdent,
+		// Length parameter is optional for Extended message format serialization
+		// and if present it will be overwritten during the serialization with the
+		// actual value.
+	}
+	request := &OpticalLineSupervisionTestResult{
+		MeBasePacket: MeBasePacket{
+			EntityClass:    me.AniGClassID,
+			EntityInstance: uint16(0x8001),
+			Extended:       true,
+		},
+		PowerFeedVoltageType:     uint8(1),
+		PowerFeedVoltage:         uint16(0x34),
+		ReceivedOpticalPowerType: uint8(3),
+		ReceivedOpticalPower:     uint16(0x67),
+		MeanOpticalLaunchType:    uint8(5),
+		MeanOpticalLaunch:        uint16(0x91),
+		LaserBiasCurrentType:     uint8(9),
+		LaserBiasCurrent:         uint16(0x34),
+		TemperatureType:          uint8(12),
+		Temperature:              uint16(0x67),
+		GeneralPurposeBuffer:     uint16(0x8901),
+	}
+	// Test serialization back to former string
+	var options gopacket.SerializeOptions
+	options.FixLengths = true
+
+	buffer := gopacket.NewSerializeBuffer()
+	err := gopacket.SerializeLayers(buffer, options, omciLayer, request)
+	assert.NoError(t, err)
+
+	outgoingPacket := buffer.Bytes()
+	reconstituted := packetToString(outgoingPacket)
+	assert.Equal(t, strings.ToLower(goodMessage), reconstituted)
+}