[VOL-3744] Adding MDS support to BBSim

Change-Id: If16511922a032511084c42727c8203ab9c9e75ec
diff --git a/internal/bbsim/devices/onu.go b/internal/bbsim/devices/onu.go
index 36fbb3e..86c70ba 100644
--- a/internal/bbsim/devices/onu.go
+++ b/internal/bbsim/devices/onu.go
@@ -79,6 +79,9 @@
 	Channel chan bbsim.Message // this Channel is to track state changes OMCI messages, EAPOL and DHCP packets
 
 	// OMCI params
+	MibDataSync uint8
+
+	// OMCI params (Used in BBR)
 	tid       uint16
 	hpTid     uint16
 	seqNumber uint16
@@ -92,13 +95,6 @@
 }
 
 func CreateONU(olt *OltDevice, pon *PonPort, id uint32, delay time.Duration, isMock bool) *Onu {
-	b := &backoff.Backoff{
-		//These are the defaults
-		Min:    5 * time.Second,
-		Max:    35 * time.Second,
-		Factor: 1.5,
-		Jitter: false,
-	}
 
 	o := Onu{
 		ID:                  id,
@@ -113,7 +109,7 @@
 		DiscoveryRetryDelay: 60 * time.Second, // this is used to send OnuDiscoveryIndications until an activate call is received
 		Flows:               []FlowKey{},
 		DiscoveryDelay:      delay,
-		Backoff:             b,
+		MibDataSync:         0,
 	}
 	o.SerialNumber = o.NewSN(olt.ID, pon.ID, id)
 	// NOTE this state machine is used to track the operational
@@ -292,6 +288,7 @@
 				msg, _ := message.Data.(bbsim.OnuIndicationMessage)
 				o.sendOnuIndication(msg, stream)
 			case bbsim.OMCI:
+				// these are OMCI messages received by the ONU
 				msg, _ := message.Data.(bbsim.OmciMessage)
 				o.handleOmciRequest(msg, stream)
 			case bbsim.UniStatusAlarm:
@@ -374,6 +371,7 @@
 				}
 				// BBR specific messages
 			case bbsim.OmciIndication:
+				// these are OMCI messages received by BBR (VOLTHA emulator)
 				msg, _ := message.Data.(bbsim.OmciIndicationMessage)
 				o.handleOmciResponse(msg, client)
 			case bbsim.SendEapolFlow:
@@ -644,14 +642,21 @@
 	var responsePkt []byte
 	switch omciMsg.MessageType {
 	case omci.MibResetRequestType:
+		o.MibDataSync = 0
+		onuLogger.WithFields(log.Fields{
+			"IntfId":       o.PonPortID,
+			"OnuId":        o.ID,
+			"SerialNumber": o.Sn(),
+		}).Debug("received-mib-reset-request-resetting-mds")
 		responsePkt, _ = omcilib.CreateMibResetResponse(omciMsg.TransactionID)
 	case omci.MibUploadRequestType:
 		responsePkt, _ = omcilib.CreateMibUploadResponse(omciMsg.TransactionID)
 	case omci.MibUploadNextRequestType:
-		responsePkt, _ = omcilib.CreateMibUploadNextResponse(omciPkt, omciMsg)
+		responsePkt, _ = omcilib.CreateMibUploadNextResponse(omciPkt, omciMsg, o.MibDataSync)
 	case omci.GetRequestType:
-		responsePkt, _ = omcilib.CreateGetResponse(omciPkt, omciMsg, o.SerialNumber)
+		responsePkt, _ = omcilib.CreateGetResponse(omciPkt, omciMsg, o.SerialNumber, o.MibDataSync)
 	case omci.SetRequestType:
+		o.MibDataSync++
 		responsePkt, _ = omcilib.CreateSetResponse(omciPkt, omciMsg)
 
 		msgObj, _ := omcilib.ParseSetRequest(omciPkt)
@@ -679,8 +684,10 @@
 			}
 		}
 	case omci.CreateRequestType:
+		o.MibDataSync++
 		responsePkt, _ = omcilib.CreateCreateResponse(omciPkt, omciMsg)
 	case omci.DeleteRequestType:
+		o.MibDataSync++
 		responsePkt, _ = omcilib.CreateDeleteResponse(omciPkt, omciMsg)
 	case omci.RebootRequestType:
 
diff --git a/internal/bbsim/devices/onu_omci_test.go b/internal/bbsim/devices/onu_omci_test.go
new file mode 100644
index 0000000..4b9cc26
--- /dev/null
+++ b/internal/bbsim/devices/onu_omci_test.go
@@ -0,0 +1,176 @@
+/*
+ * 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 devices
+
+import (
+	bbsim "github.com/opencord/bbsim/internal/bbsim/types"
+	omcilib "github.com/opencord/bbsim/internal/common/omci"
+	"github.com/opencord/omci-lib-go"
+	me "github.com/opencord/omci-lib-go/generated"
+	"github.com/opencord/voltha-protos/v4/go/openolt"
+	"gotest.tools/assert"
+	"testing"
+)
+
+var mockAttr = me.AttributeValueMap{
+	"ManagedEntityId":                     12,
+	"PortId":                              0,
+	"TContPointer":                        0,
+	"Direction":                           0,
+	"TrafficManagementPointerForUpstream": 0,
+	"TrafficDescriptorProfilePointerForUpstream":   0,
+	"PriorityQueuePointerForDownStream":            0,
+	"TrafficDescriptorProfilePointerForDownstream": 0,
+	"EncryptionKeyRing":                            0,
+}
+
+func makeOmciCreateRequest(t *testing.T) []byte {
+	omciReq := &omci.CreateRequest{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass:    me.GemPortNetworkCtpClassID,
+			EntityInstance: 12,
+		},
+		Attributes: mockAttr,
+	}
+	omciPkt, err := omcilib.Serialize(omci.CreateRequestType, omciReq, 66)
+	if err != nil {
+		t.Fatal(err.Error())
+	}
+
+	omciPkt, _ = omcilib.HexEncode(omciPkt)
+
+	return omciPkt
+}
+
+func makeOmciSetRequest(t *testing.T) []byte {
+	omciReq := &omci.SetRequest{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass:    me.GemPortNetworkCtpClassID,
+			EntityInstance: 12,
+		},
+		Attributes: mockAttr,
+	}
+	omciPkt, err := omcilib.Serialize(omci.SetRequestType, omciReq, 66)
+	if err != nil {
+		t.Fatal(err.Error())
+	}
+
+	omciPkt, _ = omcilib.HexEncode(omciPkt)
+
+	return omciPkt
+}
+
+func makeOmciDeleteRequest(t *testing.T) []byte {
+	omciReq := &omci.DeleteRequest{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass:    me.GemPortNetworkCtpClassID,
+			EntityInstance: 12,
+		},
+	}
+	omciPkt, err := omcilib.Serialize(omci.DeleteRequestType, omciReq, 66)
+	if err != nil {
+		t.Fatal(err.Error())
+	}
+
+	omciPkt, _ = omcilib.HexEncode(omciPkt)
+
+	return omciPkt
+}
+
+func makeOmciMibResetRequest(t *testing.T) []byte {
+	omciReq := &omci.MibResetRequest{
+		MeBasePacket: omci.MeBasePacket{
+			EntityClass: me.OnuDataClassID,
+		},
+	}
+	omciPkt, err := omcilib.Serialize(omci.MibResetRequestType, omciReq, 66)
+	if err != nil {
+		t.Fatal(err.Error())
+	}
+
+	omciPkt, _ = omcilib.HexEncode(omciPkt)
+
+	return omciPkt
+}
+
+func makeOmciMessage(t *testing.T, onu *Onu, pkt []byte) bbsim.OmciMessage {
+	return bbsim.OmciMessage{
+		OnuSN: onu.SerialNumber,
+		OnuID: onu.ID,
+		OmciMsg: &openolt.OmciMsg{
+			IntfId: onu.PonPortID,
+			OnuId:  onu.ID,
+			Pkt:    pkt,
+		},
+	}
+}
+
+func Test_MibDataSyncIncrease(t *testing.T) {
+	onu := createMockOnu(1, 1)
+
+	assert.Equal(t, onu.MibDataSync, uint8(0))
+
+	stream := &mockStream{
+		Calls: make(map[int]*openolt.Indication),
+	}
+
+	// send a Create and check that MDS has been increased
+	onu.handleOmciRequest(makeOmciMessage(t, onu, makeOmciCreateRequest(t)), stream)
+	assert.Equal(t, onu.MibDataSync, uint8(1))
+
+	// send a Set and check that MDS has been increased
+	onu.handleOmciRequest(makeOmciMessage(t, onu, makeOmciSetRequest(t)), stream)
+	assert.Equal(t, onu.MibDataSync, uint8(2))
+
+	// send a Delete and check that MDS has been increased
+	onu.handleOmciRequest(makeOmciMessage(t, onu, makeOmciDeleteRequest(t)), stream)
+	assert.Equal(t, onu.MibDataSync, uint8(3))
+
+	// TODO once supported MDS should increase for:
+	// - Start software download
+	// - End software download
+	// - Activate software
+	// - Commit software
+}
+
+func Test_MibDataSyncReset(t *testing.T) {
+	onu := createMockOnu(1, 1)
+	onu.MibDataSync = 192
+	assert.Equal(t, onu.MibDataSync, uint8(192))
+
+	stream := &mockStream{
+		Calls: make(map[int]*openolt.Indication),
+	}
+
+	// send a MibReset and check that MDS has reset to 0
+	onu.handleOmciRequest(makeOmciMessage(t, onu, makeOmciMibResetRequest(t)), stream)
+	assert.Equal(t, onu.MibDataSync, uint8(0))
+}
+
+func Test_MibDataSyncRotation(t *testing.T) {
+	onu := createMockOnu(1, 1)
+	onu.MibDataSync = 255
+	assert.Equal(t, onu.MibDataSync, uint8(255))
+
+	stream := &mockStream{
+		Calls: make(map[int]*openolt.Indication),
+	}
+
+	// send a request that increases the MDS, but once we're at 255 we should go back to 0 (8bit)
+	onu.handleOmciRequest(makeOmciMessage(t, onu, makeOmciDeleteRequest(t)), stream)
+	assert.Equal(t, onu.MibDataSync, uint8(0))
+}
diff --git a/internal/common/omci/create.go b/internal/common/omci/create.go
index 8e4afb3..1fcef4a 100644
--- a/internal/common/omci/create.go
+++ b/internal/common/omci/create.go
@@ -53,7 +53,7 @@
 	omciLogger.WithFields(log.Fields{
 		"EntityClass":    msgObj.EntityClass,
 		"EntityInstance": msgObj.EntityInstance,
-	}).Trace("recevied-omci-create-request")
+	}).Trace("received-omci-create-request")
 
 	response := &omci.CreateResponse{
 		MeBasePacket: omci.MeBasePacket{
@@ -63,11 +63,11 @@
 		Result: me.Success,
 	}
 
-	pkt, err := serialize(omci.CreateResponseType, response, omciMsg.TransactionID)
+	pkt, err := Serialize(omci.CreateResponseType, response, omciMsg.TransactionID)
 	if err != nil {
 		omciLogger.WithFields(log.Fields{
 			"Err": err,
-		}).Error("cannot-serialize-CreateResponse")
+		}).Error("cannot-Serialize-CreateResponse")
 		return nil, err
 	}
 
@@ -91,7 +91,7 @@
 	if err != nil {
 		omciLogger.WithField("err", err).Fatalf("Can't generate GalEnetRequest")
 	}
-	return hexEncode(pkt)
+	return HexEncode(pkt)
 }
 
 func CreateEnableUniRequest(tid uint16, uniId uint16, enabled bool, isPtp bool) ([]byte, error) {
@@ -124,7 +124,7 @@
 	if err != nil {
 		omciLogger.WithField("err", err).Fatalf("Can't generate EnableUniRequest")
 	}
-	return hexEncode(pkt)
+	return HexEncode(pkt)
 }
 
 func CreateGemPortRequest(tid uint16) ([]byte, error) {
@@ -148,5 +148,5 @@
 	if err != nil {
 		omciLogger.WithField("err", err).Fatalf("Can't generate GemPortRequest")
 	}
-	return hexEncode(pkt)
+	return HexEncode(pkt)
 }
diff --git a/internal/common/omci/delete.go b/internal/common/omci/delete.go
index c38d696..c3b7176 100644
--- a/internal/common/omci/delete.go
+++ b/internal/common/omci/delete.go
@@ -50,7 +50,7 @@
 	omciLogger.WithFields(log.Fields{
 		"EntityClass":    msgObj.EntityClass,
 		"EntityInstance": msgObj.EntityInstance,
-	}).Trace("recevied-omci-delete-request")
+	}).Trace("received-omci-delete-request")
 
 	response := &omci.DeleteResponse{
 		MeBasePacket: omci.MeBasePacket{
@@ -60,11 +60,11 @@
 		Result: me.Success,
 	}
 
-	pkt, err := serialize(omci.DeleteResponseType, response, omciMsg.TransactionID)
+	pkt, err := Serialize(omci.DeleteResponseType, response, omciMsg.TransactionID)
 	if err != nil {
 		omciLogger.WithFields(log.Fields{
 			"Err": err,
-		}).Error("cannot-serialize-DeleteResponse")
+		}).Error("cannot-Serialize-DeleteResponse")
 		return nil, err
 	}
 
diff --git a/internal/common/omci/get.go b/internal/common/omci/get.go
index 78aa98e..67ce88f 100644
--- a/internal/common/omci/get.go
+++ b/internal/common/omci/get.go
@@ -44,7 +44,7 @@
 	return msgObj, nil
 }
 
-func CreateGetResponse(omciPkt gopacket.Packet, omciMsg *omci.OMCI, onuSn *openolt.SerialNumber) ([]byte, error) {
+func CreateGetResponse(omciPkt gopacket.Packet, omciMsg *omci.OMCI, onuSn *openolt.SerialNumber, mds uint8) ([]byte, error) {
 
 	msgObj, err := ParseGetRequest(omciPkt)
 
@@ -56,7 +56,7 @@
 		"EntityClass":    msgObj.EntityClass,
 		"EntityInstance": msgObj.EntityInstance,
 		"AttributeMask":  fmt.Sprintf("%x", msgObj.AttributeMask),
-	}).Trace("recevied-omci-get-request")
+	}).Trace("received-omci-get-request")
 
 	var response *omci.GetResponse
 	switch msgObj.EntityClass {
@@ -75,7 +75,7 @@
 	case me.AniGClassID:
 		response = createAnigResponse(msgObj.AttributeMask, msgObj.EntityInstance)
 	case me.OnuDataClassID:
-		response = createOnuDataResponse(msgObj.AttributeMask, msgObj.EntityInstance)
+		response = createOnuDataResponse(msgObj.AttributeMask, msgObj.EntityInstance, mds)
 	default:
 		omciLogger.WithFields(log.Fields{
 			"EntityClass":    msgObj.EntityClass,
@@ -85,12 +85,12 @@
 		return nil, nil
 	}
 
-	pkt, err := serialize(omci.GetResponseType, response, omciMsg.TransactionID)
+	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")
+		}).Error("cannot-Serialize-Onu2gResponse")
 		return nil, err
 	}
 
@@ -330,12 +330,12 @@
 	}
 }
 
-func createOnuDataResponse(attributeMask uint16, entityID uint16) *omci.GetResponse {
+func createOnuDataResponse(attributeMask uint16, entityID uint16, mds uint8) *omci.GetResponse {
 	managedEntity, meErr := me.NewOnuData(me.ParamData{
 		EntityID: entityID,
 		Attributes: me.AttributeValueMap{
 			"ManagedEntityId": entityID,
-			"MibDataSync":     0,
+			"MibDataSync":     mds,
 		},
 	})
 
diff --git a/internal/common/omci/get_test.go b/internal/common/omci/get_test.go
index 7ba494b..ca580ed 100644
--- a/internal/common/omci/get_test.go
+++ b/internal/common/omci/get_test.go
@@ -55,33 +55,81 @@
 	return msgObj
 }
 
-func TestCreateOnu2gResponse(t *testing.T) {
-	response := createOnu2gResponse(40960, 1)
-	data, _ := serialize(omci.GetResponseType, response, 1)
+type args struct {
+	generatedPkt  *omci.GetResponse
+	transactionId uint16
+}
 
-	// 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)
+type want struct {
+	transactionId uint16
+	attributes    map[string]interface{}
+}
 
-	assert.Equal(t, omciMsg.MessageType, omci.GetResponseType)
+func TestGetResponse(t *testing.T) {
 
-	// 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)
+	// NOTE that we're not testing the SerialNumber attribute part of the ONU-G
+	// response here as it is a special case and it requires transformation.
+	// we specifically test that in TestCreateOnugResponse
+	sn := &openolt.SerialNumber{
+		VendorId:       []byte("BBSM"),
+		VendorSpecific: []byte{0, byte(1 % 256), byte(1), byte(1)},
+	}
 
-	assert.Equal(t, getResponseLayer.Result, me.Success)
+	tests := []struct {
+		name string
+		args args
+		want want
+	}{
+		{"getOnu2gResponse",
+			args{createOnu2gResponse(57344, 10), 1},
+			want{1, map[string]interface{}{"OpticalNetworkUnitManagementAndControlChannelOmccVersion": uint8(180)}},
+		},
+		{"getOnugResponse",
+			args{createOnugResponse(40960, 10, sn), 1},
+			want{1, map[string]interface{}{}},
+		},
+		{"getOnuDataResponse",
+			args{createOnuDataResponse(32768, 10, 129), 2},
+			want{2, map[string]interface{}{"MibDataSync": uint8(129)}},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+
+			data, _ := Serialize(omci.GetResponseType, tt.args.generatedPkt, tt.args.transactionId)
+
+			// 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)
+			assert.Equal(t, omciMsg.TransactionID, tt.want.transactionId)
+
+			// 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)
+
+			for k, v := range tt.want.attributes {
+				attr := getResponseLayer.Attributes[k]
+				assert.Equal(t, attr, v)
+			}
+		})
+	}
 }
 
 func TestCreateOnugResponse(t *testing.T) {
+
 	sn := &openolt.SerialNumber{
 		VendorId:       []byte("BBSM"),
 		VendorSpecific: []byte{0, byte(1 % 256), byte(1), byte(1)},
 	}
 	response := createOnugResponse(40960, 1, sn)
-	data, _ := serialize(omci.GetResponseType, response, 1)
+	data, _ := Serialize(omci.GetResponseType, response, 1)
 
 	omciMsg, omciPkt := omciBytesToMsg(t, data)
 
diff --git a/internal/common/omci/mib_test.go b/internal/common/omci/mib_test.go
index c73f616..a55eeeb 100644
--- a/internal/common/omci/mib_test.go
+++ b/internal/common/omci/mib_test.go
@@ -17,7 +17,6 @@
 package omci
 
 import (
-	"fmt"
 	"github.com/google/gopacket"
 	"github.com/opencord/omci-lib-go"
 	me "github.com/opencord/omci-lib-go/generated"
@@ -25,6 +24,10 @@
 	"testing"
 )
 
+// used to verify that the first message in the MIB Sync (OnuData)
+// reports the correct MDS
+const MDS = uint8(128)
+
 func TestCreateMibResetResponse(t *testing.T) {
 	data, _ := CreateMibResetResponse(1)
 
@@ -51,6 +54,7 @@
 	messageType   omci.MessageType
 	transactionId uint16
 	entityClass   me.ClassID
+	entityID      uint16
 	attributes    map[string]interface{}
 }
 
@@ -73,20 +77,20 @@
 		want mibExpected
 	}{
 		{"mibUploadNext-0", createTestMibUploadNextArgs(t, 1, 0),
-			mibExpected{messageType: omci.MibUploadNextResponseType, transactionId: 1, entityClass: me.OnuDataClassID, attributes: map[string]interface{}{"MibDataSync": uint8(0)}}},
+			mibExpected{messageType: omci.MibUploadNextResponseType, entityID: 0, transactionId: 1, entityClass: me.OnuDataClassID, attributes: map[string]interface{}{"MibDataSync": MDS}}},
 		{"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)}}},
+			mibExpected{messageType: omci.MibUploadNextResponseType, entityID: 0, 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)}}},
+			mibExpected{messageType: omci.MibUploadNextResponseType, entityID: 0, 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)}}},
+			mibExpected{messageType: omci.MibUploadNextResponseType, entityID: 258, 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)
+			data, _ := CreateMibUploadNextResponse(tt.args.omciPkt, tt.args.omciMsg, MDS)
 			omciMsg, omciPkt := omciBytesToMsg(t, data)
 
 			assert.Equal(t, omciMsg.MessageType, tt.want.messageType)
@@ -98,14 +102,8 @@
 			}
 
 			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())
+			assert.Equal(t, msgObj.ReportedME.GetEntityID(), tt.want.entityID)
 
 			for k, v := range tt.want.attributes {
 				attr, _ := msgObj.ReportedME.GetAttribute(k)
diff --git a/internal/common/omci/mibpackets.go b/internal/common/omci/mibpackets.go
index fe02e5d..5e25d7f 100755
--- a/internal/common/omci/mibpackets.go
+++ b/internal/common/omci/mibpackets.go
@@ -17,7 +17,6 @@
 package omci
 
 import (
-	"encoding/hex"
 	"errors"
 	"github.com/google/gopacket"
 	"github.com/opencord/omci-lib-go"
@@ -43,7 +42,7 @@
 
 // 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) {
+func Serialize(msgType omci.MessageType, request gopacket.SerializableLayer, tid uint16) ([]byte, error) {
 	omciLayer := &omci.OMCI{
 		TransactionID: tid,
 		MessageType:   msgType,
@@ -59,12 +58,6 @@
 	return buffer.Bytes(), nil
 }
 
-func hexEncode(omciPkt []byte) ([]byte, error) {
-	dst := make([]byte, hex.EncodedLen(len(omciPkt)))
-	hex.Encode(dst, omciPkt)
-	return dst, nil
-}
-
 func CreateMibResetRequest(tid uint16) ([]byte, error) {
 
 	request := &omci.MibResetRequest{
@@ -72,30 +65,29 @@
 			EntityClass: me.OnuDataClassID,
 		},
 	}
-	pkt, err := serialize(omci.MibResetRequestType, request, tid)
+	pkt, err := Serialize(omci.MibResetRequestType, request, tid)
 	if err != nil {
 		omciLogger.WithFields(log.Fields{
 			"Err": err,
-		}).Fatalf("Cannot serialize MibResetRequest")
+		}).Fatalf("Cannot Serialize MibResetRequest")
 		return nil, err
 	}
-	return hexEncode(pkt)
+	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)
+	pkt, err := Serialize(omci.MibResetResponseType, request, tid)
 	if err != nil {
 		omciLogger.WithFields(log.Fields{
 			"Err": err,
-		}).Error("Cannot serialize MibResetResponse")
+		}).Error("Cannot Serialize MibResetResponse")
 		return nil, err
 	}
 	return pkt, nil
@@ -108,14 +100,14 @@
 			// Default Instance ID is 0
 		},
 	}
-	pkt, err := serialize(omci.MibUploadRequestType, request, tid)
+	pkt, err := Serialize(omci.MibUploadRequestType, request, tid)
 	if err != nil {
 		omciLogger.WithFields(log.Fields{
 			"Err": err,
-		}).Fatalf("Cannot serialize MibUploadRequest")
+		}).Fatalf("Cannot Serialize MibUploadRequest")
 		return nil, err
 	}
-	return hexEncode(pkt)
+	return HexEncode(pkt)
 }
 
 func CreateMibUploadResponse(tid uint16) ([]byte, error) {
@@ -128,11 +120,11 @@
 		},
 		NumberOfCommands: numberOfCommands,
 	}
-	pkt, err := serialize(omci.MibUploadResponseType, request, tid)
+	pkt, err := Serialize(omci.MibUploadResponseType, request, tid)
 	if err != nil {
 		omciLogger.WithFields(log.Fields{
 			"Err": err,
-		}).Error("Cannot serialize MibUploadResponse")
+		}).Error("Cannot Serialize MibUploadResponse")
 		return nil, err
 	}
 	return pkt, nil
@@ -147,15 +139,15 @@
 		},
 		CommandSequenceNumber: seqNumber,
 	}
-	pkt, err := serialize(omci.MibUploadNextRequestType, request, tid)
+	pkt, err := Serialize(omci.MibUploadNextRequestType, request, tid)
 
 	if err != nil {
 		omciLogger.WithFields(log.Fields{
 			"Err": err,
-		}).Fatalf("Cannot serialize MibUploadNextRequest")
+		}).Fatalf("Cannot Serialize MibUploadNextRequest")
 		return nil, err
 	}
-	return hexEncode(pkt)
+	return HexEncode(pkt)
 }
 
 func ParseMibUploadNextRequest(omciPkt gopacket.Packet) (*omci.MibUploadNextRequest, error) {
@@ -174,7 +166,7 @@
 	return msgObj, nil
 }
 
-func CreateMibUploadNextResponse(omciPkt gopacket.Packet, omciMsg *omci.OMCI) ([]byte, error) {
+func CreateMibUploadNextResponse(omciPkt gopacket.Packet, omciMsg *omci.OMCI, mds uint8) ([]byte, error) {
 
 	msgObj, err := ParseMibUploadNextRequest(omciPkt)
 	if err != nil {
@@ -197,7 +189,7 @@
 	case 0:
 		reportedMe, meErr = me.NewOnuData(me.ParamData{Attributes: me.AttributeValueMap{
 			"ManagedEntityId": me.OnuDataClassID,
-			"MibDataSync":     0,
+			"MibDataSync":     mds,
 		}})
 		if meErr.GetError() != nil {
 			omciLogger.Errorf("NewOnuData %v", meErr.Error())
@@ -443,12 +435,12 @@
 		"reportedMe": reportedMe,
 	}).Trace("created-omci-mibUploadNext-response")
 
-	pkt, err := serialize(omci.MibUploadNextResponseType, response, omciMsg.TransactionID)
+	pkt, err := Serialize(omci.MibUploadNextResponseType, response, omciMsg.TransactionID)
 
 	if err != nil {
 		omciLogger.WithFields(log.Fields{
 			"Err": err,
-		}).Fatalf("Cannot serialize MibUploadNextRequest")
+		}).Fatalf("Cannot Serialize MibUploadNextRequest")
 		return nil, err
 	}
 
diff --git a/internal/common/omci/omci_base.go b/internal/common/omci/omci_base.go
index e74ec4a..7a9f499 100644
--- a/internal/common/omci/omci_base.go
+++ b/internal/common/omci/omci_base.go
@@ -18,6 +18,7 @@
 
 import (
 	"encoding/binary"
+	"encoding/hex"
 	"errors"
 	"fmt"
 	"github.com/google/gopacket"
@@ -73,3 +74,10 @@
 	}
 	return p
 }
+
+//HexEncode convert binary to hex
+func HexEncode(omciPkt []byte) ([]byte, error) {
+	dst := make([]byte, hex.EncodedLen(len(omciPkt)))
+	hex.Encode(dst, omciPkt)
+	return dst, nil
+}
diff --git a/internal/common/omci/reboot.go b/internal/common/omci/reboot.go
index e315044..0f68e02 100644
--- a/internal/common/omci/reboot.go
+++ b/internal/common/omci/reboot.go
@@ -61,11 +61,11 @@
 		Result: me.Success,
 	}
 
-	pkt, err := serialize(omci.RebootResponseType, response, omciMsg.TransactionID)
+	pkt, err := Serialize(omci.RebootResponseType, response, omciMsg.TransactionID)
 	if err != nil {
 		omciLogger.WithFields(log.Fields{
 			"Err": err,
-		}).Error("cannot-serialize-RebootResponse")
+		}).Error("cannot-Serialize-RebootResponse")
 		return nil, err
 	}
 
diff --git a/internal/common/omci/set.go b/internal/common/omci/set.go
index eeb621e..64f048f 100644
--- a/internal/common/omci/set.go
+++ b/internal/common/omci/set.go
@@ -62,11 +62,11 @@
 		Result: me.Success,
 	}
 
-	pkt, err := serialize(omci.SetResponseType, response, omciMsg.TransactionID)
+	pkt, err := Serialize(omci.SetResponseType, response, omciMsg.TransactionID)
 	if err != nil {
 		omciLogger.WithFields(log.Fields{
 			"Err": err,
-		}).Error("cannot-serialize-SetResponse")
+		}).Error("cannot-Serialize-SetResponse")
 		return nil, err
 	}