SEBA-400 Refactor omci code in preparation to make omci a go-pkg

Change-Id: Ided8514c39a178d3f2ac63924d4b4e9a6e1c3265
diff --git a/core/omci.go b/core/omci.go
index 87d2f70..4698121 100644
--- a/core/omci.go
+++ b/core/omci.go
@@ -17,54 +17,16 @@
 package core
 
 import (
-	"encoding/binary"
 	"time"
 
 	"context"
-	"errors"
 
 	"gerrit.opencord.org/voltha-bbsim/common/logger"
 	"gerrit.opencord.org/voltha-bbsim/device"
 	"gerrit.opencord.org/voltha-bbsim/protos"
 )
 
-const NumMibUploads byte = 26
-
-type OnuKey struct {
-	IntfId, OnuId uint32
-}
-
-type OnuOmciState struct {
-	gemPortId     uint16
-	mibUploadCtr  uint16
-	uniGInstance  uint8
-	tcontInstance uint8
-	pptpInstance  uint8
-	init          istate
-}
-
-type istate int
-
-const (
-	INCOMPLETE istate = iota
-	DONE
-)
-
-type OmciMsgHandler func(class OmciClass, content OmciContent, key OnuKey) ([]byte, error)
-
-var Handlers = map[OmciMsgType]OmciMsgHandler{
-	MibReset:      mibReset,
-	MibUpload:     mibUpload,
-	MibUploadNext: mibUploadNext,
-	Set:           set,
-	Create:        create,
-	Get:           get,
-	GetAllAlarms:  getAllAlarms,
-}
-
-var OnuOmciStateMap = map[OnuKey]*OnuOmciState{}
-
-func RunOmciResponder(ctx context.Context, omciOut chan openolt.OmciMsg, omciIn chan openolt.OmciIndication, onumap map[uint32][] *device.Onu, errch chan error) {
+func RunOmciResponder(ctx context.Context, omciOut chan openolt.OmciMsg, omciIn chan openolt.OmciIndication, onumap map[uint32][]*device.Onu, errch chan error) {
 	go func() { //For monitoring the OMCI states TODO: This part should be eliminated because it is out of scope of this library
 		t := time.NewTicker(1 * time.Second)
 		defer t.Stop()
@@ -86,41 +48,29 @@
 
 	go func() {
 		defer logger.Debug("Omci response process was done")
+
+		var resp openolt.OmciIndication
+
 		for {
-			var resp openolt.OmciIndication
 			select {
 			case m := <-omciOut:
-				transactionId, deviceId, msgType, class, instance, content, err := ParsePkt(HexDecode(m.Pkt))
-				if err != nil {
-					errch <- err
-					return
-				}
-
-				logger.Debug("OmciRun - transactionId: %d msgType: %d, ME Class: %d, ME Instance: %d",
-					transactionId, msgType, class, instance)
-
-				key := OnuKey{m.IntfId, m.OnuId}
-				if _, ok := OnuOmciStateMap[key]; !ok {
-					OnuOmciStateMap[key] = NewOnuOmciState()
-				}
-
-				if _, ok := Handlers[msgType]; !ok {
-					logger.Warn("Ignore omci msg (msgType %d not handled)", msgType)
+				resp_pkt, err := OmciSim(m.IntfId, m.OnuId, HexDecode(m.Pkt))
+				switch err := err.(type) {
+				case nil:
+					// Success
+					resp.IntfId = m.IntfId
+					resp.OnuId = m.OnuId
+					resp.Pkt = resp_pkt
+					omciIn <- resp
+				case *OmciError:
+					// Error in processing omci message. Log and carry on.
+					logger.Debug("%s", err.Msg)
 					continue
-				}
-
-				resp.Pkt, err = Handlers[msgType](class, content, key)
-				if err != nil {
+				default:
+					// Fatal error, exit.
 					errch <- err
 					return
 				}
-				resp.Pkt[0] = byte(transactionId >> 8)
-				resp.Pkt[1] = byte(transactionId & 0xFF)
-				resp.Pkt[2] = 0x2<<4 | byte(msgType)
-				resp.Pkt[3] = deviceId
-				resp.IntfId = m.IntfId
-				resp.OnuId = m.OnuId
-				omciIn <- resp
 			case <-ctx.Done():
 				return
 			}
@@ -142,264 +92,10 @@
 	return p
 }
 
-func NewOnuOmciState() *OnuOmciState {
-	return &OnuOmciState{gemPortId: 0, mibUploadCtr: 0, uniGInstance: 1, tcontInstance: 0, pptpInstance: 1}
-}
-
-func mibReset(class OmciClass, content OmciContent, key OnuKey) ([]byte, error) {
-	var pkt []byte
-
-	logger.Debug("Omci MibReset")
-
-	pkt = []byte{
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 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, 0x00, 0x00}
-	return pkt, nil
-}
-
-func mibUpload(class OmciClass, content OmciContent, key OnuKey) ([]byte, error) {
-	var pkt []byte
-
-	logger.Debug("Omci MibUpload")
-
-	pkt = []byte{
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 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, 0x00, 0x00}
-
-	pkt[9] = NumMibUploads // Number of subsequent MibUploadNext cmds
-
-	return pkt, nil
-}
-
-func mibUploadNext(class OmciClass, content OmciContent, key OnuKey) ([]byte, error) {
-	var pkt []byte
-
-	state := OnuOmciStateMap[key]
-
-	logger.Debug("Omci MibUploadNext %d", state.mibUploadCtr)
-
-	switch state.mibUploadCtr {
-	case 0:
-		// ONT Data (2)
-		pkt = []byte{
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
-			0x00, 0x02, 0x00, 0x00, 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}
-	case 1:
-		// Circuit Pack (6) - #1
-		pkt = []byte{
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
-			0x00, 0x06, 0x01, 0x01, 0xf0, 0x00, 0x2f, 0x04,
-			0x49, 0x53, 0x4b, 0x54, 0x71, 0xe8, 0x00, 0x80,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
-	case 2:
-		// Circuit Pack (6) - #2
-		pkt = []byte{
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
-			0x00, 0x06, 0x01, 0x01, 0x0f, 0x00, 0x42, 0x52,
-			0x43, 0x4d, 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}
-	case 3:
-		// Circuit Pack (6) - #3
-		pkt = []byte{
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
-			0x00, 0x06, 0x01, 0x01, 0x00, 0xf8, 0x20, 0x20,
-			0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-			0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-			0x20, 0x20, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
-	case 4:
-		// Circuit Pack (6) - #4
-		pkt = []byte{
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
-			0x00, 0x06, 0x01, 0x01, 0x00, 0x04, 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}
-	case 5:
-		// Circuit Pack (6) - #5
-		pkt = []byte{
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
-			0x00, 0x06, 0x01, 0x80, 0xf0, 0x00, 0xee, 0x01,
-			0x49, 0x53, 0x4b, 0x54, 0x71, 0xe8, 0x00, 0x80,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
-	case 6:
-		// Circuit Pack (6) - #6
-		pkt = []byte{
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
-			0x00, 0x06, 0x01, 0x80, 0x0f, 0x00, 0x42, 0x52,
-			0x43, 0x4d, 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}
-	case 7:
-		// Circuit Pack (6) - #7
-		pkt = []byte{
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
-			0x00, 0x06, 0x01, 0x80, 0x00, 0xf8, 0x20, 0x20,
-			0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-			0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-			0x20, 0x20, 0x00, 0x08, 0x40, 0x10, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
-	case 8:
-		// Circuit Pack (6) - #8
-		pkt = []byte{
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
-			0x00, 0x06, 0x01, 0x80, 0x00, 0x04, 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}
-	case 9, 10, 11, 12:
-		// PPTP (11)
-		pkt = []byte{
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
-			0x00, 0x0b, 0x01, 0x01, 0xff, 0xfe, 0x00, 0x2f,
-			0x00, 0x00, 0x00, 0x00, 0x03, 0x05, 0xee, 0x00,
-			0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
-		pkt[11] = state.pptpInstance // ME Instance
-		state.pptpInstance++
-	case 13, 14, 15, 16, 17, 18, 19, 20:
-		// T-CONT (262)
-		pkt = []byte{
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
-			0x01, 0x06, 0x80, 0x00, 0xe0, 0x00, 0xff, 0xff,
-			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}
-		pkt[11] = state.tcontInstance // TCONT ME Instance
-		state.tcontInstance++
-	case 21:
-		// ANI-G (263)
-		pkt = []byte{
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
-			0x01, 0x07, 0x80, 0x01, 0xff, 0xff, 0x01, 0x00,
-			0x08, 0x00, 0x30, 0x00, 0x00, 0x05, 0x09, 0x00,
-			0x00, 0xe0, 0x54, 0xff, 0xff, 0x00, 0x00, 0x0c,
-			0x63, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
-	case 22, 23, 24, 25:
-		// UNI-G (264)
-		pkt = []byte{
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
-			0x01, 0x08, 0x01, 0x01, 0xf8, 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}
-		pkt[11] = state.uniGInstance // UNI-G ME Instance
-		state.uniGInstance++
-	default:
-		logger.Error("Invalid MibUpload request %d", state.mibUploadCtr)
-		return nil, errors.New("Invalid MibUpload request")
-	}
-
-	state.mibUploadCtr++
-	return pkt, nil
-}
-
-func set(class OmciClass, content OmciContent, key OnuKey) ([]byte, error) {
-	var pkt []byte
-
-	pkt = []byte{
-		0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00}
-
-	logger.Debug("Omci Set")
-
-	return pkt, nil
-}
-
-func create(class OmciClass, content OmciContent, key OnuKey) ([]byte, error) {
-	var pkt []byte
-
-	if class == GEMPortNetworkCTP {
-		if onuOmciState, ok := OnuOmciStateMap[key]; !ok {
-			logger.Error("ONU Key Error - IntfId: %d, OnuId:", key.IntfId, key.OnuId)
-			return nil, errors.New("ONU Key Error")
-		} else {
-			onuOmciState.gemPortId = binary.BigEndian.Uint16(content[:2])
-			logger.Debug("Gem Port Id %d", onuOmciState.gemPortId)
-			OnuOmciStateMap[key].init = DONE
-		}
-	}
-
-	pkt = []byte{
-		0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 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}
-
-	logger.Debug("Omci Create")
-
-	return pkt, nil
-}
-
-func get(class OmciClass, content OmciContent, key OnuKey) ([]byte, error) {
-	var pkt []byte
-
-	pkt = []byte{
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x02, 0x01,
-		0x00, 0x20, 0xc0, 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}
-
-	logger.Debug("Omci Get")
-
-	return pkt, nil
-}
-
-func getAllAlarms(class OmciClass, content OmciContent, key OnuKey) ([]byte, error) {
-	var pkt []byte
-
-	pkt = []byte{
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
-		0x00, 0x03, 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}
-
-	logger.Debug("Omci GetAllAlarms")
-
-	return pkt, nil
-}
-
 func isAllOmciInitDone(onumap map[uint32][]*device.Onu) bool {
 	for _, onus := range onumap {
 		for _, onu := range onus {
-			key := OnuKey{onu.IntfID, onu.OnuID}
-			state := OnuOmciStateMap[key]
-			if state.init == INCOMPLETE {
+			if GetOnuOmciState(onu.OnuID, onu.IntfID) == INCOMPLETE {
 				return false
 			}
 		}
diff --git a/core/omci_common.go b/core/omci_common.go
new file mode 100644
index 0000000..d4d2e35
--- /dev/null
+++ b/core/omci_common.go
@@ -0,0 +1,31 @@
+/*
+ * 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 core
+
+import "fmt"
+
+type OmciError struct {
+	Msg string
+}
+
+func (e *OmciError) Error() string {
+	return fmt.Sprintf("%s", e.Msg)
+}
+
+type OnuKey struct {
+	IntfId, OnuId uint32
+}
diff --git a/core/omci_handlers.go b/core/omci_handlers.go
new file mode 100644
index 0000000..135ef92
--- /dev/null
+++ b/core/omci_handlers.go
@@ -0,0 +1,285 @@
+/*
+ * 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 core
+
+import (
+	"encoding/binary"
+	"errors"
+
+	"gerrit.opencord.org/voltha-bbsim/common/logger"
+)
+
+type OmciMsgHandler func(class OmciClass, content OmciContent, key OnuKey) ([]byte, error)
+
+var Handlers = map[OmciMsgType]OmciMsgHandler{
+	MibReset:      mibReset,
+	MibUpload:     mibUpload,
+	MibUploadNext: mibUploadNext,
+	Set:           set,
+	Create:        create,
+	Get:           get,
+	GetAllAlarms:  getAllAlarms,
+}
+
+func mibReset(class OmciClass, content OmciContent, key OnuKey) ([]byte, error) {
+	var pkt []byte
+
+	logger.Debug("Omci MibReset")
+
+	pkt = []byte{
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 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, 0x00, 0x00}
+	return pkt, nil
+}
+
+func mibUpload(class OmciClass, content OmciContent, key OnuKey) ([]byte, error) {
+	var pkt []byte
+
+	logger.Debug("Omci MibUpload")
+
+	pkt = []byte{
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 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, 0x00, 0x00}
+
+	pkt[9] = NumMibUploads // Number of subsequent MibUploadNext cmds
+
+	return pkt, nil
+}
+
+func mibUploadNext(class OmciClass, content OmciContent, key OnuKey) ([]byte, error) {
+	var pkt []byte
+
+	state := OnuOmciStateMap[key]
+
+	logger.Debug("Omci MibUploadNext %d", state.mibUploadCtr)
+
+	switch state.mibUploadCtr {
+	case 0:
+		// ONT Data (2)
+		pkt = []byte{
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+			0x00, 0x02, 0x00, 0x00, 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}
+	case 1:
+		// Circuit Pack (6) - #1
+		pkt = []byte{
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+			0x00, 0x06, 0x01, 0x01, 0xf0, 0x00, 0x2f, 0x04,
+			0x49, 0x53, 0x4b, 0x54, 0x71, 0xe8, 0x00, 0x80,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+	case 2:
+		// Circuit Pack (6) - #2
+		pkt = []byte{
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+			0x00, 0x06, 0x01, 0x01, 0x0f, 0x00, 0x42, 0x52,
+			0x43, 0x4d, 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}
+	case 3:
+		// Circuit Pack (6) - #3
+		pkt = []byte{
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+			0x00, 0x06, 0x01, 0x01, 0x00, 0xf8, 0x20, 0x20,
+			0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+			0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+			0x20, 0x20, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+	case 4:
+		// Circuit Pack (6) - #4
+		pkt = []byte{
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+			0x00, 0x06, 0x01, 0x01, 0x00, 0x04, 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}
+	case 5:
+		// Circuit Pack (6) - #5
+		pkt = []byte{
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+			0x00, 0x06, 0x01, 0x80, 0xf0, 0x00, 0xee, 0x01,
+			0x49, 0x53, 0x4b, 0x54, 0x71, 0xe8, 0x00, 0x80,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+	case 6:
+		// Circuit Pack (6) - #6
+		pkt = []byte{
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+			0x00, 0x06, 0x01, 0x80, 0x0f, 0x00, 0x42, 0x52,
+			0x43, 0x4d, 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}
+	case 7:
+		// Circuit Pack (6) - #7
+		pkt = []byte{
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+			0x00, 0x06, 0x01, 0x80, 0x00, 0xf8, 0x20, 0x20,
+			0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+			0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+			0x20, 0x20, 0x00, 0x08, 0x40, 0x10, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+	case 8:
+		// Circuit Pack (6) - #8
+		pkt = []byte{
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+			0x00, 0x06, 0x01, 0x80, 0x00, 0x04, 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}
+	case 9, 10, 11, 12:
+		// PPTP (11)
+		pkt = []byte{
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+			0x00, 0x0b, 0x01, 0x01, 0xff, 0xfe, 0x00, 0x2f,
+			0x00, 0x00, 0x00, 0x00, 0x03, 0x05, 0xee, 0x00,
+			0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+		pkt[11] = state.pptpInstance // ME Instance
+		state.pptpInstance++
+	case 13, 14, 15, 16, 17, 18, 19, 20:
+		// T-CONT (262)
+		pkt = []byte{
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+			0x01, 0x06, 0x80, 0x00, 0xe0, 0x00, 0xff, 0xff,
+			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}
+		pkt[11] = state.tcontInstance // TCONT ME Instance
+		state.tcontInstance++
+	case 21:
+		// ANI-G (263)
+		pkt = []byte{
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+			0x01, 0x07, 0x80, 0x01, 0xff, 0xff, 0x01, 0x00,
+			0x08, 0x00, 0x30, 0x00, 0x00, 0x05, 0x09, 0x00,
+			0x00, 0xe0, 0x54, 0xff, 0xff, 0x00, 0x00, 0x0c,
+			0x63, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+	case 22, 23, 24, 25:
+		// UNI-G (264)
+		pkt = []byte{
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+			0x01, 0x08, 0x01, 0x01, 0xf8, 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}
+		pkt[11] = state.uniGInstance // UNI-G ME Instance
+		state.uniGInstance++
+	default:
+		logger.Error("Invalid MibUpload request %d", state.mibUploadCtr)
+		return nil, errors.New("Invalid MibUpload request")
+	}
+
+	state.mibUploadCtr++
+	return pkt, nil
+}
+
+func set(class OmciClass, content OmciContent, key OnuKey) ([]byte, error) {
+	var pkt []byte
+
+	pkt = []byte{
+		0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00}
+
+	logger.Debug("Omci Set")
+
+	return pkt, nil
+}
+
+func create(class OmciClass, content OmciContent, key OnuKey) ([]byte, error) {
+	var pkt []byte
+
+	if class == GEMPortNetworkCTP {
+		if onuOmciState, ok := OnuOmciStateMap[key]; !ok {
+			logger.Error("ONU Key Error - IntfId: %d, OnuId:", key.IntfId, key.OnuId)
+			return nil, errors.New("ONU Key Error")
+		} else {
+			onuOmciState.gemPortId = binary.BigEndian.Uint16(content[:2])
+			logger.Debug("Gem Port Id %d", onuOmciState.gemPortId)
+			// FIXME
+			OnuOmciStateMap[key].state = DONE
+		}
+	}
+
+	pkt = []byte{
+		0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 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}
+
+	logger.Debug("Omci Create")
+
+	return pkt, nil
+}
+
+func get(class OmciClass, content OmciContent, key OnuKey) ([]byte, error) {
+	var pkt []byte
+
+	pkt = []byte{
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x02, 0x01,
+		0x00, 0x20, 0xc0, 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}
+
+	logger.Debug("Omci Get")
+
+	return pkt, nil
+}
+
+func getAllAlarms(class OmciClass, content OmciContent, key OnuKey) ([]byte, error) {
+	var pkt []byte
+
+	pkt = []byte{
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+		0x00, 0x03, 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}
+
+	logger.Debug("Omci GetAllAlarms")
+
+	return pkt, nil
+}
diff --git a/core/omci_mib.go b/core/omci_mib.go
new file mode 100644
index 0000000..6fba4fd
--- /dev/null
+++ b/core/omci_mib.go
@@ -0,0 +1,19 @@
+/*
+ * 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 core
+
+const NumMibUploads byte = 26
diff --git a/core/omci_sim.go b/core/omci_sim.go
new file mode 100644
index 0000000..4335e0a
--- /dev/null
+++ b/core/omci_sim.go
@@ -0,0 +1,54 @@
+/*
+ * 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 core
+
+import (
+	"gerrit.opencord.org/voltha-bbsim/common/logger"
+)
+
+func OmciSim(intfId uint32, onuId uint32, request []byte) ([]byte, error) {
+	var resp []byte
+
+	transactionId, deviceId, msgType, class, instance, content, err := ParsePkt(request)
+	if err != nil {
+		return resp, &OmciError{"Cannot parse omci msg"}
+	}
+
+	logger.Debug("OmciRun - transactionId: %d msgType: %d, ME Class: %d, ME Instance: %d",
+		transactionId, msgType, class, instance)
+
+	key := OnuKey{intfId, onuId}
+	if _, ok := OnuOmciStateMap[key]; !ok {
+		OnuOmciStateMap[key] = NewOnuOmciState()
+	}
+
+	if _, ok := Handlers[msgType]; !ok {
+		logger.Warn("Ignore omci msg (msgType %d not handled)", msgType)
+		return resp, &OmciError{"Unimplemented omci msg"}
+	}
+
+	resp, err = Handlers[msgType](class, content, key)
+	if err != nil {
+		return resp, err
+	}
+	resp[0] = byte(transactionId >> 8)
+	resp[1] = byte(transactionId & 0xFF)
+	resp[2] = 0x2<<4 | byte(msgType)
+	resp[3] = deviceId
+
+	return resp, nil
+}
diff --git a/core/omci_state.go b/core/omci_state.go
new file mode 100644
index 0000000..2e11d3e
--- /dev/null
+++ b/core/omci_state.go
@@ -0,0 +1,44 @@
+/*
+ * 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 core
+
+type OnuOmciState struct {
+	gemPortId     uint16
+	mibUploadCtr  uint16
+	uniGInstance  uint8
+	tcontInstance uint8
+	pptpInstance  uint8
+	state         istate
+}
+
+type istate int
+
+// TODO - Needs to reflect real ONU/OMCI state
+const (
+	INCOMPLETE istate = iota
+	DONE
+)
+
+var OnuOmciStateMap = map[OnuKey]*OnuOmciState{}
+
+func NewOnuOmciState() *OnuOmciState {
+	return &OnuOmciState{gemPortId: 0, mibUploadCtr: 0, uniGInstance: 1, tcontInstance: 0, pptpInstance: 1}
+}
+
+func GetOnuOmciState(onuId uint32, intfId uint32) istate {
+	key := OnuKey{intfId, onuId}
+	return (OnuOmciStateMap[key].state)
+}