diff --git a/generated/attribute.go b/generated/attribute.go
new file mode 100644
index 0000000..bc2a7dd
--- /dev/null
+++ b/generated/attribute.go
@@ -0,0 +1,773 @@
+/*
+ * 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/cboling/OMCI-parser/README.md
+ */
+
+package generated
+
+import (
+	"encoding/base64"
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"github.com/deckarep/golang-set"
+	"github.com/google/gopacket"
+	"reflect"
+	"sort"
+	"strings"
+)
+
+// Attribute types
+type AttributeType uint8
+
+const (
+	UnknownAttributeType         AttributeType = iota // Not known
+	OctetsAttributeType                               // Series of zero or more octets
+	StringAttributeType                               // Readable String
+	UnsignedIntegerAttributeType                      // Integer (0..max)
+	TableAttributeType                                // Table (of Octets)
+	SignedIntegerAttributeType                        // Signed integer, often expressed as 2's complement
+	PointerAttributeType                              // Managed Entity ID or pointer to a Managed instance
+	BitFieldAttributeType                             // Bitfield
+	EnumerationAttributeType                          // Fixed number of values (Unsigned Integers)
+	CounterAttributeType                              // Incrementing counter
+)
+
+// AttributeDefinitionMap is a map of attribute definitions with the attribute index (0..15)
+// as the key
+type AttributeDefinitionMap map[uint]AttributeDefinition
+
+// AttributeDefinition defines a single specific Managed Entity's attributes
+type AttributeDefinition struct {
+	Name          string
+	AttributeType AttributeType
+	Index         uint
+	Mask          uint16
+	DefValue      interface{}
+	Size          int        // Size of attribute in bytes. 0 indicates variable/unknown
+	Access        mapset.Set // AttributeAccess...
+	Constraint    func(interface{}) *ParamError
+	Avc           bool // If true, an AVC notification can occur for the attribute
+	Tca           bool // If true, a threshold crossing alert alarm notification can occur for the attribute
+	Optional      bool // If true, attribute is option, else mandatory
+	Deprecated    bool // If true, attribute is deprecated
+}
+
+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())
+}
+
+// GetName returns the attribute's name
+func (attr AttributeDefinition) GetName() string { return attr.Name }
+
+// GetIndex returns the attribute index )0..15)
+func (attr AttributeDefinition) GetIndex() uint { return attr.Index }
+
+// GetDefault provides the default value for an attribute if not specified
+// during its creation
+func (attr AttributeDefinition) GetDefault() interface{} { return attr.DefValue }
+
+// GetSize returns the size of the attribute. For table attributes, the size is
+// the size of a single table.
+func (attr AttributeDefinition) GetSize() int { return attr.Size }
+
+// GetAccess provides the access information (Read, Write, ...)
+func (attr AttributeDefinition) GetAccess() mapset.Set { return attr.Access }
+
+// GetConstraints returns a function that can be called for the attribute
+// that will validate the value. An appropriate error is returned if the
+// constraint fails, otherwise nil is returned to indicate that the value
+// is valid.
+func (attr AttributeDefinition) GetConstraints() func(interface{}) *ParamError {
+	return attr.Constraint
+}
+
+// IsTableAttribute returns true if the attribute is a table
+func (attr AttributeDefinition) IsTableAttribute() bool {
+	return attr.AttributeType == TableAttributeType
+}
+
+// IsCounter returns true if the attribute is a counter (usually expressed as an
+// unsigned integer)
+func (attr AttributeDefinition) IsCounter() bool {
+	return attr.AttributeType == CounterAttributeType
+}
+
+// IsBitField returns true if the attribute is a bitfield
+func (attr AttributeDefinition) IsBitField() bool {
+	return attr.AttributeType == BitFieldAttributeType
+}
+
+// IsString returns true if the attribute is a string. Strings are typically encoded
+// into fixed length files and padded with 0's
+func (attr AttributeDefinition) IsString() bool {
+	return attr.AttributeType == StringAttributeType
+}
+
+// Decode takes a slice of bytes and converts them into a value appropriate for
+// the attribute, or returns an error on failure
+func (attr *AttributeDefinition) Decode(data []byte, df gopacket.DecodeFeedback, msgType byte) (interface{}, error) {
+	if attr.IsTableAttribute() {
+		value, err := attr.tableAttributeDecode(data, df, msgType)
+		if err != nil {
+			return nil, err
+		}
+		if attr.GetConstraints() != nil {
+			if omciErr := attr.GetConstraints()(value); omciErr != nil {
+				return nil, omciErr.GetError()
+			}
+		}
+		return value, nil
+	}
+	size := attr.GetSize()
+
+	if len(data) < size {
+		df.SetTruncated()
+		return nil, NewMessageTruncatedError("packet too small for field")
+	}
+	switch attr.AttributeType {
+	case StringAttributeType, OctetsAttributeType, UnknownAttributeType:
+		value := make([]byte, size)
+		copy(value, data[:size])
+		if attr.GetConstraints() != nil {
+			if omciErr := attr.GetConstraints()(value); omciErr != nil {
+				return nil, omciErr.GetError()
+			}
+		}
+		return value, nil
+
+	default:
+		switch attr.GetSize() {
+		default:
+			value := make([]byte, size)
+			copy(value, data[:size])
+			if attr.GetConstraints() != nil {
+				if omciErr := attr.GetConstraints()(value); omciErr != nil {
+					return nil, omciErr.GetError()
+				}
+			}
+			return value, nil
+		case 1:
+			value := data[0]
+			if attr.GetConstraints() != nil {
+				if omciErr := attr.GetConstraints()(value); omciErr != nil {
+					return nil, omciErr.GetError()
+				}
+			}
+			return value, nil
+		case 2:
+			value := binary.BigEndian.Uint16(data[0:2])
+			if attr.GetConstraints() != nil {
+				if omciErr := attr.GetConstraints()(value); omciErr != nil {
+					return nil, omciErr.GetError()
+				}
+			}
+			return value, nil
+		case 4:
+			value := binary.BigEndian.Uint32(data[0:4])
+			if attr.GetConstraints() != nil {
+				if omciErr := attr.GetConstraints()(value); omciErr != nil {
+					return nil, omciErr.GetError()
+				}
+			}
+			return value, nil
+		case 8:
+			value := binary.BigEndian.Uint64(data[0:8])
+			if attr.GetConstraints() != nil {
+				omciErr := attr.GetConstraints()(value)
+				if omciErr != nil {
+					return nil, omciErr.GetError()
+				}
+			}
+			return value, nil
+		}
+	}
+}
+
+// IOctetStream interface defines a way to convert a custom type to/from an octet
+// stream.
+type IOctetStream interface {
+	ToOctetString() ([]byte, error)
+	FromOctetString([]byte) (interface{}, error)
+}
+
+// InterfaceToOctets converts an attribute value to a string of octets
+func InterfaceToOctets(input interface{}) ([]byte, error) {
+	switch values := input.(type) {
+	case []byte:
+		return values, nil
+
+	case []uint16:
+		stream := make([]byte, 2*len(values))
+		for index, value := range values {
+			binary.BigEndian.PutUint16(stream[index*2:], value)
+		}
+		return stream, nil
+
+	case []uint32:
+		stream := make([]byte, 4*len(values))
+		for index, value := range values {
+			binary.BigEndian.PutUint32(stream[index*4:], value)
+		}
+		return stream, nil
+
+	case []uint64:
+		stream := make([]byte, 8*len(values))
+		for index, value := range values {
+			binary.BigEndian.PutUint64(stream[index*8:], value)
+		}
+		return stream, nil
+
+	case IOctetStream:
+		return values.ToOctetString()
+
+	default:
+		var typeName string
+		if t := reflect.TypeOf(input); t.Kind() == reflect.Ptr {
+			typeName = "*" + t.Elem().Name()
+		} else {
+			typeName = t.Name()
+		}
+		return nil, fmt.Errorf("unable to convert input to octet string: %v", typeName)
+	}
+}
+
+// SerializeTo takes an attribute value and converts it to a slice of bytes ready
+// for transmission
+func (attr *AttributeDefinition) SerializeTo(value interface{}, b gopacket.SerializeBuffer,
+	msgType byte, bytesAvailable int) (int, error) {
+	if attr.IsTableAttribute() {
+		return attr.tableAttributeSerializeTo(value, b, msgType, bytesAvailable)
+	}
+	if value == nil {
+		return 0, fmt.Errorf("attribute: %v is nil", attr.Name)
+	}
+	size := attr.GetSize()
+	if bytesAvailable < size {
+		return 0, NewMessageTruncatedError(fmt.Sprintf("not enough space for attribute: %v", attr.Name))
+	}
+	bytes, err := b.AppendBytes(size)
+	if err != nil {
+		return 0, err
+	}
+	switch attr.AttributeType {
+	case StringAttributeType, OctetsAttributeType, UnknownAttributeType:
+		byteStream, err := InterfaceToOctets(value)
+		if err != nil {
+			return 0, err
+		}
+		copy(bytes, byteStream)
+
+	default:
+		switch size {
+		default:
+			byteStream, err := InterfaceToOctets(value)
+			if err != nil {
+				return 0, err
+			}
+			copy(bytes, byteStream)
+		case 1:
+			switch value.(type) {
+			case int:
+				bytes[0] = byte(value.(int))
+			default:
+				bytes[0] = value.(byte)
+			}
+		case 2:
+			switch value.(type) {
+			case int:
+				binary.BigEndian.PutUint16(bytes, uint16(value.(int)))
+			default:
+				binary.BigEndian.PutUint16(bytes, value.(uint16))
+			}
+		case 4:
+			switch value.(type) {
+			case int:
+				binary.BigEndian.PutUint32(bytes, uint32(value.(int)))
+			default:
+				binary.BigEndian.PutUint32(bytes, value.(uint32))
+			}
+		case 8:
+			switch value.(type) {
+			case int:
+				binary.BigEndian.PutUint64(bytes, uint64(value.(int)))
+			default:
+				binary.BigEndian.PutUint64(bytes, value.(uint64))
+			}
+		}
+	}
+	return size, nil
+}
+
+// BufferToTableAttributes takes the reconstructed octet buffer transmitted for
+// a table attribute (over many GetNextResponses) and converts it into the desired
+// format for each table row
+func (attr *AttributeDefinition) BufferToTableAttributes(data []byte) (interface{}, error) {
+	// Source is network byte order octets. Convert to proper array of slices
+	rowSize := attr.GetSize()
+	dataSize := len(data)
+	index := 0
+
+	switch rowSize {
+	default:
+		value := make([][]byte, dataSize/rowSize)
+		for offset := 0; offset < dataSize; offset += rowSize {
+			value[index] = make([]byte, rowSize)
+			copy(value[index], data[offset:])
+			index++
+		}
+		return value, nil
+	case 1:
+		value := make([]byte, dataSize)
+		copy(value, data)
+		return value, nil
+	case 2:
+		value := make([]uint16, dataSize/2)
+		for offset := 0; offset < dataSize; offset += rowSize {
+			value[offset] = binary.BigEndian.Uint16(data[offset:])
+			index++
+		}
+		return value, nil
+	case 4:
+		value := make([]uint32, dataSize/4)
+		for offset := 0; offset < dataSize; offset += rowSize {
+			value[offset] = binary.BigEndian.Uint32(data[offset:])
+			index++
+		}
+		return value, nil
+	case 8:
+		value := make([]uint64, dataSize/8)
+		for offset := 0; offset < dataSize; offset += rowSize {
+			value[offset] = binary.BigEndian.Uint64(data[offset:])
+			index++
+		}
+		return value, nil
+	}
+}
+
+func (attr *AttributeDefinition) tableAttributeDecode(data []byte, df gopacket.DecodeFeedback, msgType byte) (interface{}, error) {
+	// Serialization of a table depends on the type of message. A
+	// Review of ITU-T G.988 shows that access on tables are
+	// either Read and/or Write, never Set-by-Create
+	switch msgType {
+	default:
+		return nil, fmt.Errorf("unsupported Message Type '%v' for table serialization", msgType)
+
+	case byte(Get) | AK: // Get Response
+		// Size
+		value := binary.BigEndian.Uint32(data[0:4])
+		return value, nil
+
+	case byte(Set) | AR: // Set Request
+		fallthrough
+
+	case byte(GetNext) | AK: // Get Next Response
+		// Block of data (octets) that need to be reassembled before conversion
+		// to table/row-data.  If table attribute is not explicitly given a value
+		// we have to assume the entire data buffer is the value. The receiver of
+		// this frame will need to trim off any addtional information at the end
+		// of the last frame sequence since they (and the ONU) are the only ones
+		// who know how long the data really is.
+		size := attr.GetSize()
+		if size != 0 && len(data) < attr.GetSize() {
+			df.SetTruncated()
+			return nil, NewMessageTruncatedError("packet too small for field")
+		} else 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")
+	}
+	return nil, errors.New("TODO")
+}
+
+func (attr *AttributeDefinition) tableAttributeSerializeTo(value interface{}, b gopacket.SerializeBuffer, msgType byte,
+	bytesAvailable int) (int, error) {
+	// Serialization of a table depends on the type of message. A
+	// Review of ITU-T G.988 shows that access on tables are
+	// either Read and/or Write, never Set-by-Create
+	switch msgType {
+	default:
+		return 0, fmt.Errorf("unsupported Message Type '%v' for table serialization", msgType)
+
+	case byte(Get) | AK: // Get Response
+		// Size
+		if bytesAvailable < 4 {
+			return 0, NewMessageTruncatedError(fmt.Sprintf("not enough space for attribute: %v", attr.Name))
+		}
+		if dwordSize, ok := value.(uint32); ok {
+			bytes, err := b.AppendBytes(4)
+			if err != nil {
+				return 0, err
+			}
+			binary.BigEndian.PutUint32(bytes, dwordSize)
+			return 4, nil
+		}
+		return 0, errors.New("unexpected type for table serialization")
+
+	case byte(GetNext) | AK: // Get Next Response
+		// Values are already in network by order form
+		if data, ok := value.([]byte); ok {
+			if bytesAvailable < len(data) {
+				return 0, NewMessageTruncatedError(fmt.Sprintf("not enough space for attribute: %v", attr.Name))
+			}
+			bytes, err := b.AppendBytes(len(data))
+			if err != nil {
+				return 0, err
+			}
+			copy(bytes, data)
+			return len(data), nil
+		}
+		return 0, errors.New("unexpected type for table serialization")
+
+	case byte(Set) | AR: // Set Request
+		// TODO: For complex table types (such as extended vlan tagging config) create an
+		//       interface definition. Provide a switch type to look for that as well as for
+		//       value being a byte slice...  For now, just byte slice provided
+		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")
+	}
+	size := attr.GetSize()
+	if bytesAvailable < size {
+		return 0, NewMessageTruncatedError(fmt.Sprintf("not enough space for attribute: %v", attr.Name))
+	}
+	bytes, err := b.AppendBytes(size)
+	if err != nil {
+		return 0, err
+	}
+	switch attr.GetSize() {
+	default:
+		copy(bytes, value.([]byte))
+	case 1:
+		switch value.(type) {
+		case int:
+			bytes[0] = byte(value.(int))
+		default:
+			bytes[0] = value.(byte)
+		}
+	case 2:
+		switch value.(type) {
+		case int:
+			binary.BigEndian.PutUint16(bytes, uint16(value.(int)))
+		default:
+			binary.BigEndian.PutUint16(bytes, value.(uint16))
+		}
+	case 4:
+		switch value.(type) {
+		case int:
+			binary.BigEndian.PutUint32(bytes, uint32(value.(int)))
+		default:
+			binary.BigEndian.PutUint32(bytes, value.(uint32))
+		}
+	case 8:
+		switch value.(type) {
+		case int:
+			binary.BigEndian.PutUint64(bytes, uint64(value.(int)))
+		default:
+			binary.BigEndian.PutUint64(bytes, value.(uint64))
+		}
+	}
+	return size, nil
+}
+
+// GetAttributeDefinitionByName searches the attribute definition map for the
+// attribute with the specified name (case insensitive)
+func GetAttributeDefinitionByName(attrMap AttributeDefinitionMap, name string) (*AttributeDefinition, error) {
+	nameLower := strings.ToLower(name)
+	for _, attrVal := range attrMap {
+		if nameLower == strings.ToLower(attrVal.GetName()) {
+			return &attrVal, nil
+		}
+	}
+	return nil, errors.New(fmt.Sprintf("attribute '%s' not found", name))
+}
+
+// GetAttributeDefinitionMapKeys is a convenience functions since we may need to
+// iterate a map in key index order. Maps in Go since v1.0 the iteration order
+// of maps have been randomized.
+func GetAttributeDefinitionMapKeys(attrMap AttributeDefinitionMap) []uint {
+	var keys []uint
+	for k := range attrMap {
+		keys = append(keys, k)
+	}
+	sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] })
+	return keys
+}
+
+// GetAttributeBitmap returns the attribute bitmask for a single attribute
+func GetAttributeBitmap(attrMap AttributeDefinitionMap, name string) (uint16, error) {
+	attrDef, err := GetAttributeDefinitionByName(attrMap, name)
+	if err != nil {
+		return 0, err
+	}
+	index := attrDef.GetIndex()
+	if index == 0 {
+		return 0, errors.New("managed entity ID should not be used in an attribute bitmask")
+	}
+	return uint16(1 << (16 - index)), nil
+}
+
+// GetAttributesBitmap is a convenience functions to scan a list of attributes
+// and return the bitmask that represents them
+func GetAttributesBitmap(attrMap AttributeDefinitionMap, attributes mapset.Set) (uint16, error) {
+	var mask uint16
+	for _, def := range attrMap {
+		if attributes.Contains(def.Name) {
+			mask |= def.Mask
+			attributes.Remove(def.Name)
+		}
+	}
+	if attributes.Cardinality() > 0 {
+		return 0, fmt.Errorf("unsupported attributes: %v", attributes)
+	}
+	return mask, nil
+}
+
+// GetAttributesValueMap returns the attribute value map with uninitialized values based
+// on the attribute bitmask
+func GetAttributesValueMap(attrDefs AttributeDefinitionMap, mask uint16, access mapset.Set) (AttributeValueMap, OmciErrors) {
+	attrMap := make(AttributeValueMap, 0)
+	for index, def := range attrDefs {
+		if index == 0 {
+			continue
+		}
+		checkMask := def.Mask
+		accessOk := access == nil || def.GetAccess().Intersect(access).Cardinality() > 0
+
+		if (mask&checkMask) != 0 && accessOk {
+			attrMap[def.GetName()] = nil
+			mask &= ^checkMask
+		}
+	}
+	if mask != 0 {
+		// Return map, but signaled failed attributes
+		return attrMap, NewParameterError(mask)
+	}
+	return attrMap, NewOmciSuccess()
+}
+
+///////////////////////////////////////////////////////////////////////
+// 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
+}
+
+///////////////////////////////////////////////////////////////////////
+// Packet definitions for attributes of various types/sizes
+
+// ByteField returns an AttributeDefinition for an attribute that is encoded as a single
+// octet (8-bits).
+func ByteField(name string, attrType AttributeType, mask uint16, defVal uint8, access mapset.Set, avc bool,
+	optional bool, deprecated bool, index uint) AttributeDefinition {
+	return AttributeDefinition{
+		Name:          name,
+		AttributeType: attrType,
+		Mask:          mask,
+		Index:         index,
+		DefValue:      defVal,
+		Size:          1,
+		Access:        access,
+		Avc:           avc,
+		Optional:      optional,
+		Deprecated:    deprecated,
+	}
+}
+
+// Uint16Field returns an AttributeDefinition for an attribute that is encoded as two
+// octet (16-bits).
+func Uint16Field(name string, attrType AttributeType, mask uint16, defVal uint16, access mapset.Set, avc bool,
+	optional bool, deprecated bool, index uint) AttributeDefinition {
+	return AttributeDefinition{
+		Name:          name,
+		AttributeType: attrType,
+		Mask:          mask,
+		Index:         index,
+		DefValue:      defVal,
+		Size:          2,
+		Access:        access,
+		Avc:           avc,
+		Optional:      optional,
+		Deprecated:    deprecated,
+	}
+}
+
+// Uint32Field returns an AttributeDefinition for an attribute that is encoded as four
+// octet (32-bits).
+func Uint32Field(name string, attrType AttributeType, mask uint16, defVal uint32, access mapset.Set, avc bool,
+	optional bool, deprecated bool, index uint) AttributeDefinition {
+	return AttributeDefinition{
+		Name:          name,
+		AttributeType: attrType,
+		Mask:          mask,
+		Index:         index,
+		DefValue:      defVal,
+		Size:          4,
+		Access:        access,
+		Avc:           avc,
+		Optional:      optional,
+		Deprecated:    deprecated,
+	}
+}
+
+// Uint64Field returns an AttributeDefinition for an attribute that is encoded as eight
+// octet (64-bits).
+func Uint64Field(name string, attrType AttributeType, mask uint16, defVal uint64, access mapset.Set, avc bool,
+	optional bool, deprecated bool, index uint) AttributeDefinition {
+	return AttributeDefinition{
+		Name:          name,
+		AttributeType: attrType,
+		Mask:          mask,
+		Index:         index,
+		DefValue:      defVal,
+		Size:          8,
+		Access:        access,
+		Avc:           avc,
+		Optional:      optional,
+		Deprecated:    deprecated,
+	}
+}
+
+// MultiByteField returns an AttributeDefinition for an attribute that is encoded as multiple
+// octets that do not map into fields with a length that is 1, 2, 4, or 8 octets.
+func MultiByteField(name string, attrType AttributeType, mask uint16, size uint, defVal []byte, access mapset.Set, avc bool,
+	optional bool, deprecated bool, index uint) AttributeDefinition {
+	return AttributeDefinition{
+		Name:          name,
+		AttributeType: attrType,
+		Mask:          mask,
+		Index:         index,
+		DefValue:      defVal,
+		Size:          int(size),
+		Access:        access,
+		Avc:           avc,
+		Optional:      optional,
+		Deprecated:    deprecated,
+	}
+}
+
+// Notes on various OMCI ME Table attribute fields.  This comment will eventually be
+// removed once a good table solution is implemented.  These are not all the MEs with
+// table attributes, but probably ones I care about to support initially.
+//
+//   ME                     Notes
+//  --------------------------------------------------------------------------------------------
+//	Port-mapping package -> Combined Port table -> N * 25 sized rows (port (1) + ME(2) * 12)
+//  ONU Remote Debug     -> Reply table (N bytes)
+//  ONU3-G               -> Status snapshot recordtable M x N bytes
+//  MCAST Gem interworkTP-> IPv4 multicast adress table (12*n) (two 2 byte fields, two 4 byte fields)
+//                          IPv6 multicast adress table (24*n) (various sub-fields)
+//  L2 mcast gem TP      -> MCAST MAC addr filtering table (11 * n) (various sub-fields)
+//  MAC Bridge Port Filt -> MAC Filter table (8 * n) (3 fields, some are bits)      *** BITS ***
+//  MAC Bridge Port data -> Bridge Table (8*M) (vaius fields, some are bits)        *** BITS ***
+//  VLAN tagging filter  -> Rx Vlan tag op table (16 * n) Lots of bit fields        *** BITS ***
+//  MCAST operations profile
+//  MCAST Subscriber config info
+//  MCAST subscriber monitor
+//  OMCI                -> Two tables (N bytes and 2*N bytes)
+//  General pupose buffer   -> N bytes
+//  Enhanced security control (17 * N bytes), (16 * P Bytes) , (16 * Q bytes), and more...
+//
+// An early example of info to track
+
+// TableInfo is an early prototype of how to better model some tables that are
+// difficult to code.
+//
+// The Value member may be one of the following:
+//   nil    : Empty, no default, ...
+//   value  : A specific value that equates to one row, ie) 6  or toOctets("base64")
+//   array  : One or more rows of values.  [2]uint16{2, 3}
+type TableInfo struct {
+	Value interface{} // See comment above
+	Size  int         // Table Row Size
+}
+
+func (t *TableInfo) String() string {
+	return fmt.Sprintf("TableInfo: Size: %d, Value(s): %v", t.Size, t.Value)
+}
+
+// TableField is used to define an attribute that is a table
+func TableField(name string, attrType AttributeType, mask uint16, tableInfo TableInfo, access mapset.Set,
+	avc bool, optional bool, deprecated bool, index uint) AttributeDefinition {
+	return AttributeDefinition{
+		Name:          name,
+		AttributeType: attrType,
+		Mask:          mask,
+		Index:         index,
+		DefValue:      tableInfo.Value,
+		Size:          tableInfo.Size, //Number of elements
+		Access:        access,
+		Avc:           avc,
+		Optional:      optional,
+		Deprecated:    deprecated,
+	}
+}
+
+// UnknownField is currently not used and may be deprecated. Its original intent
+// was to be a placeholder during table attribute development
+func UnknownField(name string, mask uint16, size int, index uint) AttributeDefinition {
+	return AttributeDefinition{
+		Name:          name,
+		AttributeType: UnknownAttributeType, // Stored as octet string
+		Mask:          mask,
+		Index:         index,
+		DefValue:      nil,
+		Size:          size,
+		Access:        mapset.NewSet(Read, Write),
+		Avc:           false,
+		Optional:      false,
+		Deprecated:    false,
+	}
+}
+
+// AttributeValueMap maps an attribute (by name) to its value
+type AttributeValueMap map[string]interface{}
+
+// MergeInDefaultValues will examine the Manage Entity defaults (for non-SetByCreate attributes). This
+// function is called on a MIB Create request but is provide for external use in case it is needed
+// before the MIB entry is created
+func MergeInDefaultValues(classID ClassID, attributes AttributeValueMap) OmciErrors {
+	// Get default values for non-SetByCreate attributes
+	attrDefs, err := GetAttributesDefinitions(classID)
+	if err.StatusCode() != Success {
+		return err
+	} else if attributes == nil {
+		return NewProcessingError("Invalid (nil) Attribute Value Map referenced")
+	}
+	nilAllowed := mapset.NewSet(StringAttributeType, OctetsAttributeType, TableAttributeType)
+	for index, attrDef := range attrDefs {
+		if !attrDef.Access.Contains(SetByCreate) && index != 0 &&
+			(attrDef.DefValue != nil || nilAllowed.Contains(attrDef.AttributeType)) {
+			name := attrDef.GetName()
+			if existing, found := attributes[name]; !found || existing == nil {
+				attributes[name] = attrDef.DefValue
+			}
+		}
+	}
+	return err
+}
