[SEBA-434] Replacing omci-sim with omci-lib-go

Change-Id: I499afc9ec49bb483467ea93bd6ce3077dd0ccc6e
diff --git a/internal/common/omci/alarms.go b/internal/common/omci/alarms.go
new file mode 100644
index 0000000..aaa2fdd
--- /dev/null
+++ b/internal/common/omci/alarms.go
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018-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
+
+// CreateUniStatusAlarm will generate an Alarm packet to report that the Link is UP or DOWN
+// as a consequence of a SetRequest on PhysicalPathTerminationPointEthernetUniClassID
+func CreateUniStatusAlarm(adminState uint8, entityId uint16) []byte {
+
+	// TODO generate using omci-lib-go
+	linkMsgDown := []byte{
+		0x00, 0x00, 0x10, 0x0a, 0x00, 0x0b, 0x01, 0x01,
+		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, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+
+	linkMsgUp := []byte{
+		0x00, 0x00, 0x10, 0x0a, 0x00, 0x0b, 0x01, 0x01,
+		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, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+
+	if adminState == 0 {
+		return linkMsgUp
+	} else if adminState == 1 {
+		return linkMsgDown
+	}
+
+	return nil
+}
diff --git a/internal/common/omci/create.go b/internal/common/omci/create.go
new file mode 100644
index 0000000..8e4afb3
--- /dev/null
+++ b/internal/common/omci/create.go
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2018-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/hex"
+	"errors"
+	"github.com/google/gopacket"
+	"github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	log "github.com/sirupsen/logrus"
+	"strconv"
+)
+
+func ParseCreateRequest(omciPkt gopacket.Packet) (*omci.CreateRequest, error) {
+	msgLayer := omciPkt.Layer(omci.LayerTypeCreateRequest)
+	if msgLayer == nil {
+		err := "omci Msg layer could not be detected for LayerTypeCreateRequest"
+		omciLogger.Error(err)
+		return nil, errors.New(err)
+	}
+	msgObj, msgOk := msgLayer.(*omci.CreateRequest)
+	if !msgOk {
+		err := "omci Msg layer could not be assigned for LayerTypeCreateRequest"
+		omciLogger.Error(err)
+		return nil, errors.New(err)
+	}
+	return msgObj, nil
+}
+
+func CreateCreateResponse(omciPkt gopacket.Packet, omciMsg *omci.OMCI) ([]byte, error) {
+
+	msgObj, err := ParseCreateRequest(omciPkt)
+
+	if err != nil {
+		return nil, err
+	}
+
+	omciLogger.WithFields(log.Fields{
+		"EntityClass":    msgObj.EntityClass,
+		"EntityInstance": msgObj.EntityInstance,
+	}).Trace("recevied-omci-create-request")
+
+	response := &omci.CreateResponse{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass:    msgObj.EntityClass,
+			EntityInstance: msgObj.EntityInstance,
+		},
+		Result: me.Success,
+	}
+
+	pkt, err := serialize(omci.CreateResponseType, response, omciMsg.TransactionID)
+	if err != nil {
+		omciLogger.WithFields(log.Fields{
+			"Err": err,
+		}).Error("cannot-serialize-CreateResponse")
+		return nil, err
+	}
+
+	log.WithFields(log.Fields{
+		"TxID": strconv.FormatInt(int64(omciMsg.TransactionID), 16),
+		"pkt":  hex.EncodeToString(pkt),
+	}).Trace("omci-create-response")
+
+	return pkt, nil
+}
+
+// methods used by BBR to drive the OMCI state machine
+
+func CreateGalEnetRequest(tid uint16) ([]byte, error) {
+	params := me.ParamData{
+		EntityID:   galEthernetEID,
+		Attributes: me.AttributeValueMap{"MaximumGemPayloadSize": maxGemPayloadSize},
+	}
+	meDef, _ := me.NewGalEthernetProfile(params)
+	pkt, err := omci.GenFrame(meDef, omci.CreateRequestType, omci.TransactionID(tid))
+	if err != nil {
+		omciLogger.WithField("err", err).Fatalf("Can't generate GalEnetRequest")
+	}
+	return hexEncode(pkt)
+}
+
+func CreateEnableUniRequest(tid uint16, uniId uint16, enabled bool, isPtp bool) ([]byte, error) {
+
+	var _enabled uint8
+	if enabled {
+		_enabled = uint8(1)
+	} else {
+		_enabled = uint8(0)
+	}
+
+	data := me.ParamData{
+		EntityID: uniId,
+		Attributes: me.AttributeValueMap{
+			"AdministrativeState": _enabled,
+		},
+	}
+	var medef *me.ManagedEntity
+	var omciErr me.OmciErrors
+
+	if isPtp {
+		medef, omciErr = me.NewPhysicalPathTerminationPointEthernetUni(data)
+	} else {
+		medef, omciErr = me.NewVirtualEthernetInterfacePoint(data)
+	}
+	if omciErr != nil {
+		return nil, omciErr.GetError()
+	}
+	pkt, err := omci.GenFrame(medef, omci.SetRequestType, omci.TransactionID(tid))
+	if err != nil {
+		omciLogger.WithField("err", err).Fatalf("Can't generate EnableUniRequest")
+	}
+	return hexEncode(pkt)
+}
+
+func CreateGemPortRequest(tid uint16) ([]byte, error) {
+	params := me.ParamData{
+		EntityID: gemEID,
+		Attributes: me.AttributeValueMap{
+			"PortId":                              1,
+			"TContPointer":                        1,
+			"Direction":                           0,
+			"TrafficManagementPointerForUpstream": 0,
+			"TrafficDescriptorProfilePointerForUpstream": 0,
+			"UniCounter":                                   0,
+			"PriorityQueuePointerForDownStream":            0,
+			"EncryptionState":                              0,
+			"TrafficDescriptorProfilePointerForDownstream": 0,
+			"EncryptionKeyRing":                            0,
+		},
+	}
+	meDef, _ := me.NewGemPortNetworkCtp(params)
+	pkt, err := omci.GenFrame(meDef, omci.CreateRequestType, omci.TransactionID(tid))
+	if err != nil {
+		omciLogger.WithField("err", err).Fatalf("Can't generate GemPortRequest")
+	}
+	return hexEncode(pkt)
+}
diff --git a/internal/common/omci/delete.go b/internal/common/omci/delete.go
new file mode 100644
index 0000000..c38d696
--- /dev/null
+++ b/internal/common/omci/delete.go
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2018-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 (
+	"errors"
+	"github.com/google/gopacket"
+	"github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	log "github.com/sirupsen/logrus"
+)
+
+func ParseDeleteRequest(omciPkt gopacket.Packet) (*omci.DeleteRequest, error) {
+	msgLayer := omciPkt.Layer(omci.LayerTypeDeleteRequest)
+	if msgLayer == nil {
+		err := "omci Msg layer could not be detected for LayerTypeDeleteRequest"
+		omciLogger.Error(err)
+		return nil, errors.New(err)
+	}
+	msgObj, msgOk := msgLayer.(*omci.DeleteRequest)
+	if !msgOk {
+		err := "omci Msg layer could not be assigned for LayerTypeDeleteRequest"
+		omciLogger.Error(err)
+		return nil, errors.New(err)
+	}
+	return msgObj, nil
+}
+
+func CreateDeleteResponse(omciPkt gopacket.Packet, omciMsg *omci.OMCI) ([]byte, error) {
+	msgObj, err := ParseDeleteRequest(omciPkt)
+
+	if err != nil {
+		return nil, err
+	}
+
+	omciLogger.WithFields(log.Fields{
+		"EntityClass":    msgObj.EntityClass,
+		"EntityInstance": msgObj.EntityInstance,
+	}).Trace("recevied-omci-delete-request")
+
+	response := &omci.DeleteResponse{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass:    msgObj.EntityClass,
+			EntityInstance: msgObj.EntityInstance,
+		},
+		Result: me.Success,
+	}
+
+	pkt, err := serialize(omci.DeleteResponseType, response, omciMsg.TransactionID)
+	if err != nil {
+		omciLogger.WithFields(log.Fields{
+			"Err": err,
+		}).Error("cannot-serialize-DeleteResponse")
+		return nil, err
+	}
+
+	return pkt, nil
+}
diff --git a/internal/common/omci/get.go b/internal/common/omci/get.go
new file mode 100644
index 0000000..64a7968
--- /dev/null
+++ b/internal/common/omci/get.go
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2018-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/hex"
+	"errors"
+	"fmt"
+	"github.com/google/gopacket"
+	"github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	log "github.com/sirupsen/logrus"
+	"strconv"
+)
+
+func ParseGetRequest(omciPkt gopacket.Packet) (*omci.GetRequest, error) {
+	msgLayer := omciPkt.Layer(omci.LayerTypeGetRequest)
+	if msgLayer == nil {
+		err := "omci Msg layer could not be detected for LayerTypeGetRequest"
+		omciLogger.Error(err)
+		return nil, errors.New(err)
+	}
+	msgObj, msgOk := msgLayer.(*omci.GetRequest)
+	if !msgOk {
+		err := "omci Msg layer could not be assigned for LayerTypeGetRequest"
+		omciLogger.Error(err)
+		return nil, errors.New(err)
+	}
+	return msgObj, nil
+}
+
+func CreateGetResponse(omciPkt gopacket.Packet, omciMsg *omci.OMCI) ([]byte, error) {
+
+	msgObj, err := ParseGetRequest(omciPkt)
+
+	if err != nil {
+		return nil, err
+	}
+
+	omciLogger.WithFields(log.Fields{
+		"EntityClass":    msgObj.EntityClass,
+		"EntityInstance": msgObj.EntityInstance,
+		"AttributeMask":  fmt.Sprintf("%x", msgObj.AttributeMask),
+	}).Trace("recevied-omci-get-request")
+
+	var response *omci.GetResponse
+	switch msgObj.EntityClass {
+	case me.Onu2GClassID:
+		response = createOnu2gResponse(msgObj.AttributeMask, msgObj.EntityInstance)
+	case me.OnuGClassID:
+		response = createOnugResponse(msgObj.AttributeMask, msgObj.EntityInstance)
+	case me.SoftwareImageClassID:
+		response = createSoftwareImageResponse(msgObj.AttributeMask, msgObj.EntityInstance)
+	case me.IpHostConfigDataClassID:
+		response = createIpHostResponse(msgObj.AttributeMask, msgObj.EntityInstance)
+	case me.UniGClassID:
+		response = createUnigResponse(msgObj.AttributeMask, msgObj.EntityInstance)
+	case me.PhysicalPathTerminationPointEthernetUniClassID:
+		response = createPptpResponse(msgObj.AttributeMask, msgObj.EntityInstance)
+	case me.AniGClassID:
+		response = createAnigResponse(msgObj.AttributeMask, msgObj.EntityInstance)
+	case me.OnuDataClassID:
+		response = createOnuDataResponse(msgObj.AttributeMask, msgObj.EntityInstance)
+	default:
+		omciLogger.WithFields(log.Fields{
+			"EntityClass":    msgObj.EntityClass,
+			"EntityInstance": msgObj.EntityInstance,
+			"AttributeMask":  fmt.Sprintf("%x", msgObj.AttributeMask),
+		}).Warnf("do-not-know-how-to-handle-get-request-for-me-class")
+		return nil, nil
+	}
+
+	pkt, err := serialize(omci.GetResponseType, response, omciMsg.TransactionID)
+	if err != nil {
+		omciLogger.WithFields(log.Fields{
+			"Err":  err,
+			"TxID": strconv.FormatInt(int64(omciMsg.TransactionID), 16),
+		}).Error("cannot-serialize-Onu2gResponse")
+		return nil, err
+	}
+
+	log.WithFields(log.Fields{
+		"TxID": strconv.FormatInt(int64(omciMsg.TransactionID), 16),
+		"pkt":  hex.EncodeToString(pkt),
+	}).Trace("omci-get-response")
+
+	return pkt, nil
+}
+
+func createOnu2gResponse(attributeMask uint16, entityID uint16) *omci.GetResponse {
+
+	managedEntity, meErr := me.NewOnu2G(me.ParamData{
+		EntityID: entityID,
+		Attributes: me.AttributeValueMap{
+			"ManagedEntityId": entityID,
+			"EquipmentId":     toOctets("BBSM", 20),
+			"OpticalNetworkUnitManagementAndControlChannelOmccVersion": 180,
+			"VendorProductCode":                           0,
+			"SecurityCapability":                          1,
+			"SecurityMode":                                1,
+			"TotalPriorityQueueNumber":                    1,
+			"TotalTrafficSchedulerNumber":                 1,
+			"Deprecated":                                  1,
+			"TotalGemPortIdNumber":                        32,
+			"Sysuptime":                                   319389947, // NOTE need to be smarter?
+			"ConnectivityCapability":                      127,
+			"CurrentConnectivityMode":                     5,
+			"QualityOfServiceQosConfigurationFlexibility": 48,
+			"PriorityQueueScaleFactor":                    1,
+		},
+	})
+
+	if meErr.GetError() != nil {
+		omciLogger.Errorf("NewOnu2G %v", meErr.Error())
+		return nil
+	}
+
+	return &omci.GetResponse{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass: me.Onu2GClassID,
+		},
+		Attributes:    managedEntity.GetAttributeValueMap(),
+		AttributeMask: attributeMask,
+		Result:        me.Success,
+	}
+}
+
+func createOnugResponse(attributeMask uint16, entityID uint16) *omci.GetResponse {
+	return &omci.GetResponse{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass:    me.OnuGClassID,
+			EntityInstance: entityID,
+		},
+		Attributes: me.AttributeValueMap{
+			"ManagedEntityId":         entityID,
+			"VendorId":                toOctets("BBSM", 4),
+			"Version":                 toOctets("v0.0.1", 14),
+			"SerialNumber":            toOctets("QkJTTQAKAAE=", 8),
+			"TrafficManagementOption": 0,
+			"Deprecated":              0,
+			"BatteryBackup":           0,
+			"AdministrativeState":     0,
+			"OperationalState":        0,
+			"OnuSurvivalTime":         10,
+			"LogicalOnuId":            toOctets("BBSM", 24),
+			"LogicalPassword":         toOctets("BBSM", 12),
+			"CredentialsStatus":       0,
+			"ExtendedTcLayerOptions":  0,
+		},
+		Result:        me.Success,
+		AttributeMask: attributeMask,
+	}
+}
+
+func createSoftwareImageResponse(attributeMask uint16, entityInstance uint16) *omci.GetResponse {
+	// NOTE that we need send the response for the correct ME Instance or the adapter won't process it
+	return &omci.GetResponse{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass:    me.SoftwareImageClassID,
+			EntityInstance: entityInstance,
+		},
+		Attributes: me.AttributeValueMap{
+			"ManagedEntityId": 0,
+			"Version":         toOctets("v0.0.1", 14),
+			"IsCommitted":     1,
+			"IsActive":        1,
+			"IsValid":         1,
+			"ProductCode":     toOctets("product-code", 25),
+			"ImageHash":       toOctets("broadband-sim", 16),
+		},
+		Result:        me.Success,
+		AttributeMask: attributeMask,
+	}
+}
+
+func createIpHostResponse(attributeMask uint16, entityInstance uint16) *omci.GetResponse {
+	return &omci.GetResponse{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass:    me.IpHostConfigDataClassID,
+			EntityInstance: entityInstance,
+		},
+		Attributes: me.AttributeValueMap{
+			"ManagedEntityId": 0,
+			"MacAddress":      toOctets("aabbcc", 6),
+		},
+		Result:        me.Success,
+		AttributeMask: attributeMask,
+	}
+}
+
+func createUnigResponse(attributeMask uint16, entityID uint16) *omci.GetResponse {
+	managedEntity, meErr := me.NewUniG(me.ParamData{
+		EntityID: entityID,
+		Attributes: me.AttributeValueMap{
+			"ManagedEntityId":             entityID,
+			"Deprecated":                  0,
+			"AdministrativeState":         0,
+			"ManagementCapability":        0,
+			"NonOmciManagementIdentifier": 1,
+			"RelayAgentOptions":           1,
+		},
+	})
+
+	if meErr.GetError() != nil {
+		omciLogger.Errorf("NewUniG %v", meErr.Error())
+		return nil
+	}
+
+	return &omci.GetResponse{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass: me.UniGClassID,
+		},
+		Attributes:    managedEntity.GetAttributeValueMap(),
+		AttributeMask: attributeMask,
+		Result:        me.Success,
+	}
+}
+
+func createPptpResponse(attributeMask uint16, entityID uint16) *omci.GetResponse {
+	managedEntity, meErr := me.NewPhysicalPathTerminationPointEthernetUni(me.ParamData{
+		EntityID: entityID,
+		Attributes: me.AttributeValueMap{
+			"ManagedEntityId":               entityID,
+			"ExpectedType":                  0,
+			"SensedType":                    0,
+			"AutoDetectionConfiguration":    0,
+			"EthernetLoopbackConfiguration": 0,
+			"AdministrativeState":           0,
+			"OperationalState":              0,
+			"ConfigurationInd":              0,
+			"MaxFrameSize":                  0,
+			"DteOrDceInd":                   0,
+			"PauseTime":                     0,
+			"BridgedOrIpInd":                0,
+			"Arc":                           0,
+			"ArcInterval":                   0,
+			"PppoeFilter":                   0,
+			"PowerControl":                  0,
+		},
+	})
+
+	if meErr.GetError() != nil {
+		omciLogger.Errorf("NewPhysicalPathTerminationPointEthernetUni %v", meErr.Error())
+		return nil
+	}
+
+	return &omci.GetResponse{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass: me.PhysicalPathTerminationPointEthernetUniClassID,
+		},
+		Attributes:    managedEntity.GetAttributeValueMap(),
+		AttributeMask: attributeMask,
+		Result:        me.Success,
+	}
+}
+
+func createAnigResponse(attributeMask uint16, entityID uint16) *omci.GetResponse {
+	managedEntity, meErr := me.NewAniG(me.ParamData{
+		EntityID: entityID,
+		Attributes: me.AttributeValueMap{
+			"ManagedEntityId":             entityID,
+			"SrIndication":                0,
+			"TotalTcontNumber":            0,
+			"GemBlockLength":              0,
+			"PiggybackDbaReporting":       0,
+			"Deprecated":                  0,
+			"SignalFailThreshold":         0,
+			"SignalDegradeThreshold":      0,
+			"Arc":                         0,
+			"ArcInterval":                 0,
+			"OpticalSignalLevel":          0,
+			"LowerOpticalThreshold":       0,
+			"UpperOpticalThreshold":       0,
+			"OnuResponseTime":             0,
+			"TransmitOpticalLevel":        0,
+			"LowerTransmitPowerThreshold": 0,
+			"UpperTransmitPowerThreshold": 0,
+		},
+	})
+
+	if meErr.GetError() != nil {
+		omciLogger.Errorf("NewAniG %v", meErr.Error())
+		return nil
+	}
+
+	return &omci.GetResponse{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass: me.AniGClassID,
+		},
+		Attributes:    managedEntity.GetAttributeValueMap(),
+		AttributeMask: attributeMask,
+		Result:        me.Success,
+	}
+}
+
+func createOnuDataResponse(attributeMask uint16, entityID uint16) *omci.GetResponse {
+	managedEntity, meErr := me.NewOnuData(me.ParamData{
+		EntityID: entityID,
+		Attributes: me.AttributeValueMap{
+			"ManagedEntityId": entityID,
+			"MibDataSync":     0,
+		},
+	})
+
+	if meErr.GetError() != nil {
+		omciLogger.Errorf("NewOnuData %v", meErr.Error())
+		return nil
+	}
+
+	return &omci.GetResponse{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass: me.OnuDataClassID,
+		},
+		Attributes:    managedEntity.GetAttributeValueMap(),
+		AttributeMask: attributeMask,
+		Result:        me.Success,
+	}
+}
+
+func toOctets(str string, size int) []byte {
+	asciiBytes := []byte(str)
+
+	if len(asciiBytes) < size {
+		missing := size - len(asciiBytes)
+		for i := 0; i < missing; i++ {
+			asciiBytes = append(asciiBytes, []byte{0x00}[0])
+		}
+	}
+	return asciiBytes
+}
diff --git a/internal/common/omci/get_test.go b/internal/common/omci/get_test.go
new file mode 100644
index 0000000..0ab6d04
--- /dev/null
+++ b/internal/common/omci/get_test.go
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2018-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 (
+	"github.com/google/gopacket"
+	"github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"gotest.tools/assert"
+	"testing"
+)
+
+func omciBytesToMsg(t *testing.T, data []byte) (*omci.OMCI, *gopacket.Packet) {
+	packet := gopacket.NewPacket(data, omci.LayerTypeOMCI, gopacket.NoCopy)
+	if packet == nil {
+		t.Fatal("could not decode rxMsg as OMCI")
+	}
+	omciLayer := packet.Layer(omci.LayerTypeOMCI)
+	if omciLayer == nil {
+		t.Fatal("could not decode omci layer")
+	}
+	omciMsg, ok := omciLayer.(*omci.OMCI)
+	if !ok {
+		t.Fatal("could not assign omci layer")
+	}
+	return omciMsg, &packet
+}
+
+func omciToGetResponse(t *testing.T, omciPkt *gopacket.Packet) *omci.GetResponse {
+	msgLayer := (*omciPkt).Layer(omci.LayerTypeGetResponse)
+	if msgLayer == nil {
+		t.Fatal("omci Msg layer could not be detected for GetResponse - handling of MibSyncChan stopped")
+	}
+	msgObj, msgOk := msgLayer.(*omci.GetResponse)
+	if !msgOk {
+		t.Fatal("omci Msg layer could not be assigned for GetResponse - handling of MibSyncChan stopped")
+	}
+	return msgObj
+}
+
+func TestCreateOnu2gResponse(t *testing.T) {
+	response := createOnu2gResponse(40960, 1)
+	data, _ := serialize(omci.GetResponseType, response, 1)
+
+	// emulate the openonu-go behavior:
+	// omci_cc.receiveMessage process the message (creates a gopacket and extracts the OMCI layer) and invokes a callback
+	// in the GetResponse case omci_cc.receiveOmciResponse
+	// then the OmciMessage (gopacket + OMIC layer) is is published on a channel
+	omciMsg, omciPkt := omciBytesToMsg(t, data)
+
+	assert.Equal(t, omciMsg.MessageType, omci.GetResponseType)
+
+	// that is read by myb_sync.processMibSyncMessages
+	// the myb_sync.handleOmciMessage is called and then
+	// myb_sync.handleOmciGetResponseMessage where we extract the GetResponse layer
+	getResponseLayer := omciToGetResponse(t, omciPkt)
+
+	assert.Equal(t, getResponseLayer.Result, me.Success)
+}
+
+func TestCreateOnugResponse(t *testing.T) {
+	response := createOnugResponse(40960, 1)
+	data, _ := serialize(omci.GetResponseType, response, 1)
+
+	omciMsg, omciPkt := omciBytesToMsg(t, data)
+
+	assert.Equal(t, omciMsg.MessageType, omci.GetResponseType)
+
+	getResponseLayer := omciToGetResponse(t, omciPkt)
+
+	assert.Equal(t, getResponseLayer.Result, me.Success)
+}
diff --git a/internal/common/omci/mib_test.go b/internal/common/omci/mib_test.go
new file mode 100644
index 0000000..c73f616
--- /dev/null
+++ b/internal/common/omci/mib_test.go
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2018-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 (
+	"fmt"
+	"github.com/google/gopacket"
+	"github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"gotest.tools/assert"
+	"testing"
+)
+
+func TestCreateMibResetResponse(t *testing.T) {
+	data, _ := CreateMibResetResponse(1)
+
+	omciMsg, omciPkt := omciBytesToMsg(t, data)
+
+	assert.Equal(t, omciMsg.MessageType, omci.MibResetResponseType)
+
+	msgLayer := (*omciPkt).Layer(omci.LayerTypeMibResetResponse)
+	msgObj, msgOk := msgLayer.(*omci.MibResetResponse)
+	if !msgOk {
+		t.Fail()
+	}
+
+	assert.Equal(t, msgObj.Result, me.Success)
+}
+
+// types for TestCreateMibUploadNextResponse test
+type mibArgs struct {
+	omciPkt gopacket.Packet
+	omciMsg *omci.OMCI
+}
+
+type mibExpected struct {
+	messageType   omci.MessageType
+	transactionId uint16
+	entityClass   me.ClassID
+	attributes    map[string]interface{}
+}
+
+func createTestMibUploadNextArgs(t *testing.T, tid uint16, seqNumber uint16) mibArgs {
+	mibUploadNext, _ := CreateMibUploadNextRequest(tid, seqNumber)
+	mibUploadNext = hexDecode(mibUploadNext)
+	mibUploadNextMsg, mibUploadNextPkt := omciBytesToMsg(t, mibUploadNext)
+
+	return mibArgs{
+		omciPkt: *mibUploadNextPkt,
+		omciMsg: mibUploadNextMsg,
+	}
+}
+
+func TestCreateMibUploadNextResponse(t *testing.T) {
+
+	tests := []struct {
+		name string
+		args mibArgs
+		want mibExpected
+	}{
+		{"mibUploadNext-0", createTestMibUploadNextArgs(t, 1, 0),
+			mibExpected{messageType: omci.MibUploadNextResponseType, transactionId: 1, entityClass: me.OnuDataClassID, attributes: map[string]interface{}{"MibDataSync": uint8(0)}}},
+		{"mibUploadNext-1", createTestMibUploadNextArgs(t, 2, 1),
+			mibExpected{messageType: omci.MibUploadNextResponseType, transactionId: 2, entityClass: me.CircuitPackClassID, attributes: map[string]interface{}{"Type": uint8(47), "NumberOfPorts": uint8(4)}}},
+		{"mibUploadNext-4", createTestMibUploadNextArgs(t, 3, 4),
+			mibExpected{messageType: omci.MibUploadNextResponseType, transactionId: 3, entityClass: me.CircuitPackClassID, attributes: map[string]interface{}{"PowerShedOverride": uint32(0)}}},
+		{"mibUploadNext-10", createTestMibUploadNextArgs(t, 4, 10),
+			mibExpected{messageType: omci.MibUploadNextResponseType, transactionId: 4, entityClass: me.CircuitPackClassID, attributes: map[string]interface{}{"SensedType": uint8(47)}}},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+
+			// create the packet starting from the mibUploadNextRequest
+			data, _ := CreateMibUploadNextResponse(tt.args.omciPkt, tt.args.omciMsg)
+			omciMsg, omciPkt := omciBytesToMsg(t, data)
+
+			assert.Equal(t, omciMsg.MessageType, tt.want.messageType)
+
+			msgLayer := (*omciPkt).Layer(omci.LayerTypeMibUploadNextResponse)
+			msgObj, msgOk := msgLayer.(*omci.MibUploadNextResponse)
+			if !msgOk {
+				t.Fail()
+			}
+
+			assert.Equal(t, omciMsg.TransactionID, tt.want.transactionId) // tid
+			// GetAttribute("ManagedEntityId") returns nil,
+			// msgObj.EntityClass is always OnuDataClassID
+			// how do we check this?
+			//meId, _ := msgObj.ReportedME.GetAttribute("ManagedEntityId")
+			//assert.Equal(t, meId, tt.want.entityClass)
+			//assert.Equal(t, msgObj.EntityClass, tt.want.entityClass)
+
+			fmt.Println(msgObj.EntityInstance, msgObj.ReportedME.GetEntityID())
+
+			for k, v := range tt.want.attributes {
+				attr, _ := msgObj.ReportedME.GetAttribute(k)
+				assert.Equal(t, attr, v)
+			}
+		})
+	}
+
+}
diff --git a/internal/common/omci/mibpackets.go b/internal/common/omci/mibpackets.go
index b21da4d..fe02e5d 100755
--- a/internal/common/omci/mibpackets.go
+++ b/internal/common/omci/mibpackets.go
@@ -18,10 +18,10 @@
 
 import (
 	"encoding/hex"
-	"github.com/cboling/omci"
-	me "github.com/cboling/omci/generated"
+	"errors"
 	"github.com/google/gopacket"
-	omcisim "github.com/opencord/omci-sim"
+	"github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
 	log "github.com/sirupsen/logrus"
 )
 
@@ -41,6 +41,8 @@
 	RxHandler   rxFrameParser
 }
 
+// NOTE this is basically the same as https://github.com/opencord/voltha-openonu-adapter-go/blob/master/internal/pkg/onuadaptercore/omci_cc.go#L545-L564
+// we should probably move it in "omci-lib-go"
 func serialize(msgType omci.MessageType, request gopacket.SerializableLayer, tid uint16) ([]byte, error) {
 	omciLayer := &omci.OMCI{
 		TransactionID: tid,
@@ -63,57 +65,11 @@
 	return dst, nil
 }
 
-func DecodeOmci(payload []byte) (omci.MessageType, gopacket.Packet) {
-	// Perform base OMCI decode (common to all requests)
-	packet := gopacket.NewPacket(payload, omci.LayerTypeOMCI, gopacket.NoCopy)
-
-	if omciLayer := packet.Layer(omci.LayerTypeOMCI); omciLayer != nil {
-
-		omciObj, omciOk := omciLayer.(*omci.OMCI)
-		if !omciOk {
-			panic("Not Expected") // TODO: Do something better or delete...
-		}
-		if byte(omciObj.MessageType) & ^me.AK == 0 {
-			// Not a response, silently discard
-			return 0, nil
-		}
-		return omciObj.MessageType, packet
-	}
-
-	// FIXME
-	// if we can't properly decode the packet, try using shad helper method
-	// most likely this won't be necessary once we move omci-sim to use cboling/omci
-	// to generate packets
-	_, _, msgType, _, _, _, err := omcisim.ParsePkt(payload)
-	if err != nil {
-		return 0, nil
-	}
-	if msgType == omcisim.MibReset {
-		return omci.MibResetResponseType, nil
-	}
-	if msgType == omcisim.MibUpload {
-		return omci.MibUploadResponseType, nil
-	}
-	if msgType == omcisim.MibUploadNext {
-		return omci.MibUploadNextResponseType, nil
-	}
-	if msgType == omcisim.Create {
-		return omci.CreateResponseType, nil
-	}
-	if msgType == omcisim.Set {
-		return omci.SetResponseType, nil
-	}
-
-	omciLogger.Warnf("omci-sim returns msgType: %d", msgType)
-
-	return 0, nil
-}
-
 func CreateMibResetRequest(tid uint16) ([]byte, error) {
 
 	request := &omci.MibResetRequest{
 		MeBasePacket: omci.MeBasePacket{
-			EntityClass: me.OnuDataClassId,
+			EntityClass: me.OnuDataClassID,
 		},
 	}
 	pkt, err := serialize(omci.MibResetRequestType, request, tid)
@@ -126,10 +82,29 @@
 	return hexEncode(pkt)
 }
 
+func CreateMibResetResponse(tid uint16) ([]byte, error) {
+
+	// TODO reset MDX
+	request := &omci.MibResetResponse{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass: me.OnuDataClassID,
+		},
+		Result: me.Success,
+	}
+	pkt, err := serialize(omci.MibResetResponseType, request, tid)
+	if err != nil {
+		omciLogger.WithFields(log.Fields{
+			"Err": err,
+		}).Error("Cannot serialize MibResetResponse")
+		return nil, err
+	}
+	return pkt, nil
+}
+
 func CreateMibUploadRequest(tid uint16) ([]byte, error) {
 	request := &omci.MibUploadRequest{
 		MeBasePacket: omci.MeBasePacket{
-			EntityClass: me.OnuDataClassId,
+			EntityClass: me.OnuDataClassID,
 			// Default Instance ID is 0
 		},
 	}
@@ -143,11 +118,31 @@
 	return hexEncode(pkt)
 }
 
+func CreateMibUploadResponse(tid uint16) ([]byte, error) {
+
+	numberOfCommands := uint16(291) //NOTE should this be configurable? (not until we have moved all the messages away from omci-sim)
+
+	request := &omci.MibUploadResponse{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass: me.OnuDataClassID,
+		},
+		NumberOfCommands: numberOfCommands,
+	}
+	pkt, err := serialize(omci.MibUploadResponseType, request, tid)
+	if err != nil {
+		omciLogger.WithFields(log.Fields{
+			"Err": err,
+		}).Error("Cannot serialize MibUploadResponse")
+		return nil, err
+	}
+	return pkt, nil
+}
+
 func CreateMibUploadNextRequest(tid uint16, seqNumber uint16) ([]byte, error) {
 
 	request := &omci.MibUploadNextRequest{
 		MeBasePacket: omci.MeBasePacket{
-			EntityClass: me.OnuDataClassId,
+			EntityClass: me.OnuDataClassID,
 			// Default Instance ID is 0
 		},
 		CommandSequenceNumber: seqNumber,
@@ -163,123 +158,299 @@
 	return hexEncode(pkt)
 }
 
-// Return true if msg is an Omci Test Request
-func IsTestRequest(payload []byte) (bool, error) {
-	_, _, msgType, _, _, _, err := omcisim.ParsePkt(payload)
-	if err != nil {
-		return false, err
+func ParseMibUploadNextRequest(omciPkt gopacket.Packet) (*omci.MibUploadNextRequest, error) {
+	msgLayer := omciPkt.Layer(omci.LayerTypeMibUploadNextRequest)
+	if msgLayer == nil {
+		err := "omci Msg layer could not be detected for LayerTypeMibUploadNextRequest"
+		omciLogger.Error(err)
+		return nil, errors.New(err)
 	}
-
-	return ((msgType & 0x1F) == 18), nil
+	msgObj, msgOk := msgLayer.(*omci.MibUploadNextRequest)
+	if !msgOk {
+		err := "omci Msg layer could not be assigned for MibUploadNextRequest"
+		omciLogger.Error(err)
+		return nil, errors.New(err)
+	}
+	return msgObj, nil
 }
 
-func BuildTestResult(payload []byte) ([]byte, error) {
-	transactionId, deviceId, _, class, instance, _, err := omcisim.ParsePkt(payload)
+func CreateMibUploadNextResponse(omciPkt gopacket.Packet, omciMsg *omci.OMCI) ([]byte, error) {
 
+	msgObj, err := ParseMibUploadNextRequest(omciPkt)
 	if err != nil {
-		return []byte{}, err
+		err := "omci Msg layer could not be assigned for LayerTypeGetRequest"
+		omciLogger.Error(err)
+		return nil, errors.New(err)
 	}
 
-	resp := make([]byte, 48)
-	resp[0] = byte(transactionId >> 8)
-	resp[1] = byte(transactionId & 0xFF)
-	resp[2] = 27 // Upper nibble 0x0 is fixed (0000), Lower nibbles defines msg type (TestResult=27)
-	resp[3] = deviceId
-	resp[4] = byte(class >> 8)
-	resp[5] = byte(class & 0xFF)
-	resp[6] = byte(instance >> 8)
-	resp[7] = byte(instance & 0xFF)
-	// Each of these is a 1-byte code
-	// follow by a 2-byte (high, low) value
-	resp[8] = 1 // power feed voltage
-	resp[9] = 0
-	resp[10] = 123 // 123 mV, 20 mv res --> 6mv
-	resp[11] = 3   // received optical power
-	resp[12] = 1
-	resp[13] = 200 // 456 decibel-microwatts, 0.002 dB res --> 0.912 db-mw
-	resp[14] = 5   // mean optical launch power
-	resp[15] = 3
-	resp[16] = 21 // 789 uA, 0.002 dB res --> 1.578 db-mw
-	resp[17] = 9  // laser bias current
-	resp[18] = 3
-	resp[19] = 244 // 1012 uA, 2uA res --> 505 ua
-	resp[20] = 12  // temperature
-	resp[21] = 38
-	resp[22] = 148 // 9876 deg C, 1/256 resolution --> 38.57 Deg C
+	omciLogger.WithFields(log.Fields{
+		"EntityClass":           msgObj.EntityClass,
+		"EntityInstance":        msgObj.EntityInstance,
+		"CommandSequenceNumber": msgObj.CommandSequenceNumber,
+	}).Trace("received-omci-mibUploadNext-request")
 
-	return resp, nil
-}
+	// depending on the sequenceNumber we'll report a different
+	reportedMe := &me.ManagedEntity{}
+	var meErr me.OmciErrors
+	//var entityInstance uint16
+	switch msgObj.CommandSequenceNumber {
+	case 0:
+		reportedMe, meErr = me.NewOnuData(me.ParamData{Attributes: me.AttributeValueMap{
+			"ManagedEntityId": me.OnuDataClassID,
+			"MibDataSync":     0,
+		}})
+		if meErr.GetError() != nil {
+			omciLogger.Errorf("NewOnuData %v", meErr.Error())
+		}
 
-// TODO understand and refactor
-
-func CreateGalEnetRequest(tid uint16) ([]byte, error) {
-	params := me.ParamData{
-		EntityID:   galEthernetEID,
-		Attributes: me.AttributeValueMap{"MaximumGemPayloadSize": maxGemPayloadSize},
-	}
-	meDef, _ := me.NewGalEthernetProfile(params)
-	pkt, err := omci.GenFrame(meDef, omci.CreateRequestType, omci.TransactionID(tid))
-	if err != nil {
-		omciLogger.WithField("err", err).Fatalf("Can't generate GalEnetRequest")
-	}
-	return hexEncode(pkt)
-}
-
-func CreateEnableUniRequest(tid uint16, uniId uint16, enabled bool, isPtp bool) ([]byte, error) {
-
-	var _enabled uint8
-	if enabled {
-		_enabled = uint8(1)
-	} else {
-		_enabled = uint8(0)
+	case 1:
+		reportedMe, meErr = me.NewCircuitPack(me.ParamData{Attributes: me.AttributeValueMap{
+			"ManagedEntityId": me.CircuitPackClassID,
+			"Type":            47,
+			"NumberOfPorts":   4,
+			"SerialNumber":    toOctets("BBSM-Circuit-Pack", 20),
+			"Version":         toOctets("v0.0.1", 20),
+		}})
+		if meErr.GetError() != nil {
+			omciLogger.Errorf("NewCircuitPack %v", meErr.Error())
+		}
+	case 2:
+		reportedMe, meErr = me.NewCircuitPack(me.ParamData{Attributes: me.AttributeValueMap{
+			"ManagedEntityId":     me.CircuitPackClassID,
+			"VendorId":            "ONF",
+			"AdministrativeState": 0,
+			"OperationalState":    0,
+			"BridgedOrIpInd":      0,
+		}})
+		if meErr.GetError() != nil {
+			omciLogger.Errorf("NewCircuitPack %v", meErr.Error())
+		}
+	case 3:
+		reportedMe, meErr = me.NewCircuitPack(me.ParamData{Attributes: me.AttributeValueMap{
+			"ManagedEntityId":             me.CircuitPackClassID,
+			"EquipmentId":                 toOctets("BBSM-Circuit-Pack", 20),
+			"CardConfiguration":           0,
+			"TotalTContBufferNumber":      0,
+			"TotalPriorityQueueNumber":    8,
+			"TotalTrafficSchedulerNumber": 0,
+		}})
+		if meErr.GetError() != nil {
+			omciLogger.Errorf("NewCircuitPack %v", meErr.Error())
+		}
+	case 4:
+		reportedMe, meErr = me.NewCircuitPack(me.ParamData{Attributes: me.AttributeValueMap{
+			"ManagedEntityId":   me.CircuitPackClassID,
+			"PowerShedOverride": uint32(0),
+		}})
+		if meErr.GetError() != nil {
+			omciLogger.Errorf("NewCircuitPack %v", meErr.Error())
+		}
+	case 5:
+		reportedMe, meErr = me.NewCircuitPack(me.ParamData{Attributes: me.AttributeValueMap{
+			"ManagedEntityId": me.CircuitPackClassID,
+			"Type":            238,
+			"NumberOfPorts":   1,
+			"SerialNumber":    toOctets("BBSM-Circuit-Pack-2", 20),
+			"Version":         toOctets("v0.0.1", 20),
+		}})
+		if meErr.GetError() != nil {
+			omciLogger.Errorf("NewCircuitPack %v", meErr.Error())
+		}
+	case 6:
+		reportedMe, meErr = me.NewCircuitPack(me.ParamData{Attributes: me.AttributeValueMap{
+			"ManagedEntityId":     me.CircuitPackClassID,
+			"VendorId":            "ONF",
+			"AdministrativeState": 0,
+			"OperationalState":    0,
+			"BridgedOrIpInd":      0,
+		}})
+		if meErr.GetError() != nil {
+			omciLogger.Errorf("NewCircuitPack %v", meErr.Error())
+		}
+	case 7:
+		reportedMe, meErr = me.NewCircuitPack(me.ParamData{Attributes: me.AttributeValueMap{
+			"ManagedEntityId":             me.CircuitPackClassID,
+			"EquipmentId":                 toOctets("BBSM-Circuit-Pack", 20),
+			"CardConfiguration":           0,
+			"TotalTContBufferNumber":      8,
+			"TotalPriorityQueueNumber":    40,
+			"TotalTrafficSchedulerNumber": 10,
+		}})
+		if meErr.GetError() != nil {
+			omciLogger.Errorf("NewCircuitPack %v", meErr.Error())
+		}
+	case 8:
+		reportedMe, meErr = me.NewCircuitPack(me.ParamData{Attributes: me.AttributeValueMap{
+			"ManagedEntityId":   me.CircuitPackClassID,
+			"PowerShedOverride": uint32(0),
+		}})
+		if meErr.GetError() != nil {
+			omciLogger.Errorf("NewCircuitPack %v", meErr.Error())
+		}
+	case 9, 10, 11, 12:
+		// NOTE we're reporting for different UNIs, the IDs are 257, 258, 259, 260
+		meInstance := 248 + msgObj.CommandSequenceNumber
+		reportedMe, meErr = me.NewPhysicalPathTerminationPointEthernetUni(me.ParamData{
+			EntityID: meInstance,
+			Attributes: me.AttributeValueMap{
+				"ExpectedType":                  0,
+				"SensedType":                    47,
+				"AutoDetectionConfiguration":    0,
+				"EthernetLoopbackConfiguration": 0,
+				"AdministrativeState":           0,
+				"OperationalState":              0,
+				"ConfigurationInd":              3,
+				"MaxFrameSize":                  1518,
+				"DteOrDceInd":                   0,
+				"PauseTime":                     0,
+				"BridgedOrIpInd":                2,
+				"Arc":                           0,
+				"ArcInterval":                   0,
+				"PppoeFilter":                   0,
+				"PowerControl":                  0,
+			}})
+		if meErr.GetError() != nil {
+			omciLogger.Errorf("NewPhysicalPathTerminationPointEthernetUni %v", meErr.Error())
+		}
+	case 13, 14, 15, 16, 17, 18, 19, 20:
+		// TODO report different MeID (see omci-sim pcap filter "frame[22:2] == 01:06")
+		reportedMe, meErr = me.NewTCont(me.ParamData{Attributes: me.AttributeValueMap{
+			"ManagedEntityId": me.TContClassID,
+			"AllocId":         0,
+		}})
+		if meErr.GetError() != nil {
+			omciLogger.Errorf("NewTCont %v", meErr.Error())
+		}
+	case 21:
+		reportedMe, meErr = me.NewAniG(me.ParamData{Attributes: me.AttributeValueMap{
+			"ManagedEntityId":             me.AniGClassID,
+			"SrIndication":                1,
+			"TotalTcontNumber":            8,
+			"GemBlockLength":              30,
+			"PiggybackDbaReporting":       0,
+			"Deprecated":                  0,
+			"SignalFailThreshold":         5,
+			"SignalDegradeThreshold":      9,
+			"Arc":                         0,
+			"ArcInterval":                 0,
+			"OpticalSignalLevel":          57428,
+			"LowerOpticalThreshold":       255,
+			"UpperOpticalThreshold":       255,
+			"OnuResponseTime":             0,
+			"TransmitOpticalLevel":        3171,
+			"LowerTransmitPowerThreshold": 129,
+			"UpperTransmitPowerThreshold": 129,
+		}})
+		if meErr.GetError() != nil {
+			omciLogger.Errorf("NewAniG %v", meErr.Error())
+		}
+	case 22, 23, 24, 25:
+		// TODO report different MeID (see omci-sim pcap filter "frame[22:2] == 01:08")
+		reportedMe, meErr = me.NewUniG(me.ParamData{Attributes: me.AttributeValueMap{
+			"ManagedEntityId":     me.UniGClassID,
+			"Deprecated":          0,
+			"AdministrativeState": 0,
+		}})
+		if meErr.GetError() != nil {
+			omciLogger.Errorf("NewUniG %v", meErr.Error())
+		}
+	case 26, 30, 34, 38, 42, 46, 50, 54,
+		58, 62, 66, 70, 74, 78, 82, 86,
+		90, 94, 98, 102, 106, 110, 114, 118,
+		122, 126, 130, 134, 138, 142, 146, 150,
+		154, 158, 162, 166, 170, 174, 178, 182,
+		186, 190, 194, 198, 202, 206, 210, 214,
+		218, 222, 226, 230, 234, 238, 242, 246,
+		250, 254, 258, 262, 266, 270, 274, 278:
+	case 27, 31, 35, 39, 43, 47, 51, 55,
+		59, 63, 67, 71, 75, 79, 83, 87,
+		91, 95, 99, 103, 107, 111, 115, 119,
+		123, 127, 131, 135, 139, 143, 147, 151,
+		155, 159, 163, 167, 171, 175, 179, 183,
+		187, 191, 195, 199, 203, 207, 211, 215,
+		219, 223, 227, 231, 235, 239, 243, 247,
+		251, 255, 259, 263, 267, 271, 275, 279:
+	case 28, 32, 36, 40, 44, 48, 52, 56,
+		60, 64, 68, 72, 76, 80, 84, 88,
+		92, 96, 100, 104, 108, 112, 116, 120,
+		124, 128, 132, 136, 140, 144, 148, 152,
+		156, 160, 164, 168, 172, 176, 180, 184,
+		188, 192, 196, 200, 204, 208, 212, 216,
+		220, 224, 228, 232, 236, 240, 244, 248,
+		252, 256, 260, 264, 268, 272, 276, 280:
+	case 29, 33, 37, 41, 45, 49, 53, 57,
+		61, 65, 69, 73, 77, 81, 85, 89,
+		93, 97, 101, 105, 109, 113, 117, 121,
+		125, 129, 133, 137, 141, 145, 149, 153,
+		157, 161, 165, 169, 173, 177, 181, 185,
+		189, 193, 197, 201, 205, 209, 213, 217,
+		221, 225, 229, 233, 237, 241, 245, 249,
+		253, 257, 261, 265, 269, 273, 277, 281:
+		reportedMe, meErr = me.NewPriorityQueue(me.ParamData{Attributes: me.AttributeValueMap{
+			"ManagedEntityId":                                     me.PriorityQueueClassID,
+			"QueueConfigurationOption":                            0,
+			"MaximumQueueSize":                                    100,
+			"AllocatedQueueSize":                                  100,
+			"DiscardBlockCounterResetInterval":                    0,
+			"ThresholdValueForDiscardedBlocksDueToBufferOverflow": 0,
+			"RelatedPort":                                         80010000, // does this need to change?
+			"TrafficSchedulerPointer":                             8008,     // does this need to change?
+			"Weight":                                              1,
+			"BackPressureOperation":                               1,
+			"BackPressureTime":                                    0,
+			"BackPressureOccurQueueThreshold":                     0,
+			"BackPressureClearQueueThreshold":                     0,
+		}})
+		if meErr.GetError() != nil {
+			omciLogger.Errorf("NewPriorityQueue %v", meErr.Error())
+		}
+	case 282, 283, 284, 285, 286, 287, 288, 289:
+		reportedMe, meErr = me.NewTrafficScheduler(me.ParamData{Attributes: me.AttributeValueMap{
+			"ManagedEntityId":         me.TrafficSchedulerClassID,
+			"TContPointer":            8008, // NOTE does this need to change?
+			"TrafficSchedulerPointer": 0,
+			"Policy":                  02,
+			"PriorityWeight":          0,
+		}})
+		if meErr.GetError() != nil {
+			omciLogger.Errorf("NewTrafficScheduler %v", meErr.Error())
+		}
+	case 290:
+		reportedMe, meErr = me.NewOnu2G(me.ParamData{Attributes: me.AttributeValueMap{
+			"ManagedEntityId":             me.Onu2GClassID,
+			"TotalPriorityQueueNumber":    40,
+			"SecurityMode":                1,
+			"TotalTrafficSchedulerNumber": 8,
+			"TotalGemPortIdNumber":        0,
+			"Sysuptime":                   0,
+		}})
+		if meErr.GetError() != nil {
+			omciLogger.Errorf("NewOnu2G %v", meErr.Error())
+		}
+	default:
+		omciLogger.Warn("unsupported-CommandSequenceNumber-in-mib-upload-next", msgObj.CommandSequenceNumber)
+		return nil, nil
 	}
 
-	data := me.ParamData{
-		EntityID: uniId,
-		Attributes: me.AttributeValueMap{
-			"AdministrativeState": _enabled,
+	response := &omci.MibUploadNextResponse{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass: me.OnuDataClassID,
 		},
+		ReportedME: *reportedMe,
 	}
-	var medef *me.ManagedEntity
-	var omciErr me.OmciErrors
 
-	if isPtp {
-		medef, omciErr = me.NewPhysicalPathTerminationPointEthernetUni(data)
-	} else {
-		medef, omciErr = me.NewVirtualEthernetInterfacePoint(data)
-	}
-	if omciErr != nil {
-		return nil, omciErr.GetError()
-	}
-	pkt, err := omci.GenFrame(medef, omci.SetRequestType, omci.TransactionID(tid))
+	omciLogger.WithFields(log.Fields{
+		"reportedMe": reportedMe,
+	}).Trace("created-omci-mibUploadNext-response")
+
+	pkt, err := serialize(omci.MibUploadNextResponseType, response, omciMsg.TransactionID)
+
 	if err != nil {
-		omciLogger.WithField("err", err).Fatalf("Can't generate EnableUniRequest")
+		omciLogger.WithFields(log.Fields{
+			"Err": err,
+		}).Fatalf("Cannot serialize MibUploadNextRequest")
+		return nil, err
 	}
-	return hexEncode(pkt)
-}
 
-func CreateGemPortRequest(tid uint16) ([]byte, error) {
-	params := me.ParamData{
-		EntityID: gemEID,
-		Attributes: me.AttributeValueMap{
-			"PortId":                              1,
-			"TContPointer":                        1,
-			"Direction":                           0,
-			"TrafficManagementPointerForUpstream": 0,
-			"TrafficDescriptorProfilePointerForUpstream": 0,
-			"UniCounter":                                   0,
-			"PriorityQueuePointerForDownStream":            0,
-			"EncryptionState":                              0,
-			"TrafficDescriptorProfilePointerForDownstream": 0,
-			"EncryptionKeyRing":                            0,
-		},
-	}
-	meDef, _ := me.NewGemPortNetworkCtp(params)
-	pkt, err := omci.GenFrame(meDef, omci.CreateRequestType, omci.TransactionID(tid))
-	if err != nil {
-		omciLogger.WithField("err", err).Fatalf("Can't generate GemPortRequest")
-	}
-	return hexEncode(pkt)
+	return pkt, nil
 }
-
-// END TODO
diff --git a/internal/common/omci/omci_base.go b/internal/common/omci/omci_base.go
new file mode 100644
index 0000000..e74ec4a
--- /dev/null
+++ b/internal/common/omci/omci_base.go
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2018-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"
+	"github.com/opencord/omci-lib-go"
+	log "github.com/sirupsen/logrus"
+)
+
+// ParseOpenOltOmciPacket receive an OMCI packet in the openolt format and returns
+// an OMCI Layer as per omci-lib-go
+func ParseOpenOltOmciPacket(pkt []byte) (gopacket.Packet, *omci.OMCI, error) {
+	rxMsg := hexDecode(pkt)
+
+	// NOTE this is may not be needed, VOLTHA sends the correct message
+	if len(rxMsg) >= 44 {
+		trailerLenData := rxMsg[42:44]
+		trailerLen := binary.BigEndian.Uint16(trailerLenData)
+		if trailerLen != 40 { // invalid base Format entry -> autocorrect
+			binary.BigEndian.PutUint16(rxMsg[42:44], 40)
+			omciLogger.Trace("cc-corrected-omci-message: trailer len inserted")
+		}
+	} else {
+		omciLogger.WithFields(log.Fields{"Length": len(rxMsg)}).Error("received omci-message too small for OmciBaseFormat - abort")
+		return nil, nil, errors.New("received omci-message too small for OmciBaseFormat - abort")
+	}
+
+	packet := gopacket.NewPacket(rxMsg, omci.LayerTypeOMCI, gopacket.NoCopy)
+	if packet == nil {
+		omciLogger.Error("omci-message could not be decoded")
+		return nil, nil, errors.New("omci-message could not be decoded")
+	}
+	omciLayer := packet.Layer(omci.LayerTypeOMCI)
+	if omciLayer == nil {
+		omciLogger.Error("omci-message could not decode omci layer")
+		return nil, nil, fmt.Errorf("omci-message could not decode omci layer")
+	}
+	parsed, ok := omciLayer.(*omci.OMCI)
+	if !ok {
+		omciLogger.Error("omci-message could not assign omci layer")
+		return nil, nil, errors.New("omci-message could not assign omci layer")
+	}
+
+	return packet, parsed, nil
+}
+
+// hexDecode converts the hex encoding to binary
+func hexDecode(pkt []byte) []byte {
+	p := make([]byte, len(pkt)/2)
+	for i, j := 0, 0; i < len(pkt); i, j = i+2, j+1 {
+		// Go figure this ;)
+		u := (pkt[i] & 15) + (pkt[i]>>6)*9
+		l := (pkt[i+1] & 15) + (pkt[i+1]>>6)*9
+		p[j] = u<<4 + l
+	}
+	return p
+}
diff --git a/internal/common/omci/reboot.go b/internal/common/omci/reboot.go
new file mode 100644
index 0000000..e315044
--- /dev/null
+++ b/internal/common/omci/reboot.go
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2018-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 (
+	"errors"
+	"github.com/google/gopacket"
+	"github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	log "github.com/sirupsen/logrus"
+)
+
+func ParseRebootRequest(omciPkt gopacket.Packet) (*omci.RebootRequest, error) {
+	msgLayer := omciPkt.Layer(omci.LayerTypeRebootRequest)
+	if msgLayer == nil {
+		err := "omci Msg layer could not be detected for LayerTypeRebootRequest"
+		omciLogger.Error(err)
+		return nil, errors.New(err)
+	}
+	msgObj, msgOk := msgLayer.(*omci.RebootRequest)
+	if !msgOk {
+		err := "omci Msg layer could not be assigned for LayerTypeRebootRequest"
+		omciLogger.Error(err)
+		return nil, errors.New(err)
+	}
+	return msgObj, nil
+}
+
+func CreateRebootResponse(omciPkt gopacket.Packet, omciMsg *omci.OMCI) ([]byte, error) {
+
+	msgObj, err := ParseRebootRequest(omciPkt)
+
+	if err != nil {
+		return nil, err
+	}
+
+	omciLogger.WithFields(log.Fields{
+		"EntityClass":    msgObj.EntityClass,
+		"EntityInstance": msgObj.EntityInstance,
+	}).Trace("received-omci-set-request")
+
+	response := &omci.SetResponse{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass:    msgObj.EntityClass,
+			EntityInstance: msgObj.EntityInstance,
+		},
+		Result: me.Success,
+	}
+
+	pkt, err := serialize(omci.RebootResponseType, response, omciMsg.TransactionID)
+	if err != nil {
+		omciLogger.WithFields(log.Fields{
+			"Err": err,
+		}).Error("cannot-serialize-RebootResponse")
+		return nil, err
+	}
+
+	return pkt, nil
+
+}
diff --git a/internal/common/omci/set.go b/internal/common/omci/set.go
new file mode 100644
index 0000000..eeb621e
--- /dev/null
+++ b/internal/common/omci/set.go
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2018-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 (
+	"errors"
+	"github.com/google/gopacket"
+	"github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	log "github.com/sirupsen/logrus"
+)
+
+func ParseSetRequest(omciPkt gopacket.Packet) (*omci.SetRequest, error) {
+	msgLayer := omciPkt.Layer(omci.LayerTypeSetRequest)
+	if msgLayer == nil {
+		err := "omci Msg layer could not be detected for LayerTypeSetRequest"
+		omciLogger.Error(err)
+		return nil, errors.New(err)
+	}
+	msgObj, msgOk := msgLayer.(*omci.SetRequest)
+	if !msgOk {
+		err := "omci Msg layer could not be assigned for LayerTypeSetRequest"
+		omciLogger.Error(err)
+		return nil, errors.New(err)
+	}
+	return msgObj, nil
+}
+
+func CreateSetResponse(omciPkt gopacket.Packet, omciMsg *omci.OMCI) ([]byte, error) {
+
+	msgObj, err := ParseSetRequest(omciPkt)
+
+	if err != nil {
+		return nil, err
+	}
+
+	omciLogger.WithFields(log.Fields{
+		"EntityClass":    msgObj.EntityClass,
+		"EntityInstance": msgObj.EntityInstance,
+		"AttributeMask":  msgObj.AttributeMask,
+	}).Trace("received-omci-set-request")
+
+	response := &omci.SetResponse{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass:    msgObj.EntityClass,
+			EntityInstance: msgObj.EntityInstance,
+		},
+		Result: me.Success,
+	}
+
+	pkt, err := serialize(omci.SetResponseType, response, omciMsg.TransactionID)
+	if err != nil {
+		omciLogger.WithFields(log.Fields{
+			"Err": err,
+		}).Error("cannot-serialize-SetResponse")
+		return nil, err
+	}
+
+	return pkt, nil
+
+}
diff --git a/internal/common/omci/test.go b/internal/common/omci/test.go
new file mode 100644
index 0000000..40398ba
--- /dev/null
+++ b/internal/common/omci/test.go
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2018-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 (
+	"errors"
+	"github.com/google/gopacket"
+	"github.com/opencord/omci-lib-go"
+)
+
+func ParseTestRequest(omciPkt gopacket.Packet) (*omci.TestRequest, error) {
+	msgLayer := omciPkt.Layer(omci.LayerTypeGetRequest)
+	if msgLayer == nil {
+		err := "omci Msg layer could not be detected for LayerTypeTestRequest"
+		omciLogger.Error(err)
+		return nil, errors.New(err)
+	}
+	msgObj, msgOk := msgLayer.(*omci.TestRequest)
+	if !msgOk {
+		err := "omci Msg layer could not be assigned for LayerTypeTestRequest"
+		omciLogger.Error(err)
+		return nil, errors.New(err)
+	}
+	return msgObj, nil
+}
+
+// Return true if msg is an Omci Test Request
+func IsTestRequest(payload []byte) (bool, error) {
+	_, omciMsg, err := ParseOpenOltOmciPacket(payload)
+	if err != nil {
+		return false, err
+	}
+
+	return omciMsg.MessageType == omci.TestRequestType, nil
+}
+
+func BuildTestResult(payload []byte) ([]byte, error) {
+
+	omciPkt, omciMsg, err := ParseOpenOltOmciPacket(payload)
+
+	//transactionId, deviceId, _, class, instance, _, err := omcisim.ParsePkt(payload)
+
+	if err != nil {
+		return []byte{}, err
+	}
+
+	testRequest, err := ParseTestRequest(omciPkt)
+	if err != nil {
+		return []byte{}, err
+	}
+
+	// TODO create a TestResponse using omci-lib-go
+	resp := make([]byte, 48)
+	resp[0] = byte(omciMsg.TransactionID >> 8)
+	resp[1] = byte(omciMsg.TransactionID & 0xFF)
+	resp[2] = 27 // Upper nibble 0x0 is fixed (0000), Lower nibbles defines msg type (TestResult=27)
+	resp[3] = byte(omciMsg.DeviceIdentifier)
+	resp[4] = byte(omciMsg.MessageType)
+	resp[5] = byte(omciMsg.MessageType & 0xFF)
+	resp[6] = byte(testRequest.EntityInstance >> 8)
+	resp[7] = byte(testRequest.EntityInstance & 0xFF)
+	// Each of these is a 1-byte code
+	// follow by a 2-byte (high, low) value
+	resp[8] = 1 // power feed voltage
+	resp[9] = 0
+	resp[10] = 123 // 123 mV, 20 mv res --> 6mv
+	resp[11] = 3   // received optical power
+	resp[12] = 1
+	resp[13] = 200 // 456 decibel-microwatts, 0.002 dB res --> 0.912 db-mw
+	resp[14] = 5   // mean optical launch power
+	resp[15] = 3
+	resp[16] = 21 // 789 uA, 0.002 dB res --> 1.578 db-mw
+	resp[17] = 9  // laser bias current
+	resp[18] = 3
+	resp[19] = 244 // 1012 uA, 2uA res --> 505 ua
+	resp[20] = 12  // temperature
+	resp[21] = 38
+	resp[22] = 148 // 9876 deg C, 1/256 resolution --> 38.57 Deg C
+
+	return resp, nil
+}