SEBA-336 - Gemport handling for packet-in

Change-Id: Iec3ca370d32d064b186f613480632a824285f9a8
diff --git a/core/core_server.go b/core/core_server.go
index 841bf24..8ebdaa0 100644
--- a/core/core_server.go
+++ b/core/core_server.go
@@ -57,8 +57,8 @@
 	cancel       context.CancelFunc
 	state        coreState
 	stateChan    chan coreState
-	omciIn       chan OmciMsg
-	omciOut      chan OmciMsg
+	omciIn       chan openolt.OmciIndication
+	omciOut      chan openolt.OmciMsg
 }
 
 type Packet struct {
@@ -80,7 +80,7 @@
        <-              <-
 */
 
-func NewCore(opt *option, omciOut chan OmciMsg, omciIn chan OmciMsg) *Server {
+func NewCore(opt *option, omciOut chan openolt.OmciMsg, omciIn chan openolt.OmciIndication) *Server {
 	// TODO: make it decent
 	oltid := opt.oltid
 	npon := opt.npon
@@ -357,7 +357,7 @@
 		select {
 		case msg := <-s.omciIn:
 			logger.Debug("OLT %d send omci indication, IF %v (ONU-ID: %v) pkt:%x.", s.Olt.ID, msg.IntfId, msg.OnuId, msg.Pkt)
-			omci := &openolt.Indication_OmciInd{OmciInd: &openolt.OmciIndication{IntfId: msg.IntfId, OnuId: msg.OnuId, Pkt: msg.Pkt}}
+			omci := &openolt.Indication_OmciInd{OmciInd: &msg}
 			if err := stream.Send(&openolt.Indication{Data: omci}); err != nil {
 				logger.Error("send omci indication failed.", err)
 				continue
@@ -504,9 +504,15 @@
 }
 
 func getGemPortID(intfid uint32, onuid uint32) (uint32, error) {
-	idx := uint32(0)
-	return 1024 + (((MAX_ONUS_PER_PON*intfid + onuid - 1) * 7) + idx), nil
-	//return uint32(1032 + 8 * (vid - 1)), nil
+	key := OnuKey{intfid, onuid}
+	if onuState, ok := Onus[key]; !ok {
+		idx := uint32(0)
+		// Backwards compatible with bbsim_olt adapter
+		return 1024 + (((MAX_ONUS_PER_PON*intfid + onuid - 1) * 7) + idx), nil
+	} else {
+		// FIXME - Gem Port ID is 2 bytes - fix openolt.proto
+		return uint32(onuState.gemPortId), nil
+	}
 }
 
 func getOnuBySN(onumap map[uint32][]*device.Onu, sn *openolt.SerialNumber) (*device.Onu, error) {
diff --git a/core/grpc_service.go b/core/grpc_service.go
index ac0c57d..cd8a108 100644
--- a/core/grpc_service.go
+++ b/core/grpc_service.go
@@ -100,13 +100,8 @@
 }
 
 func (s *Server) OmciMsgOut(c context.Context, msg *openolt.OmciMsg) (*openolt.Empty, error) {
-	var resp OmciMsg
 	logger.Debug("OLT %d receives OmciMsgOut to IF %v (ONU-ID: %v) pkt:%x.", s.Olt.ID, msg.IntfId, msg.OnuId, msg.Pkt)
-	resp.IntfId = msg.IntfId
-	resp.OnuId = msg.OnuId
-	resp.Pkt = make([]byte, len(msg.Pkt))
-	copy(resp.Pkt, msg.Pkt)
-	s.omciOut <- resp
+	s.omciOut <- *msg
 	return new(openolt.Empty), nil
 }
 
diff --git a/core/mediator.go b/core/mediator.go
index 0ad0696..2bf2c40 100644
--- a/core/mediator.go
+++ b/core/mediator.go
@@ -26,6 +26,7 @@
 	"sync"
 
 	"gerrit.opencord.org/voltha-bbsim/common/logger"
+	"gerrit.opencord.org/voltha-bbsim/protos"
 	log "github.com/sirupsen/logrus"
 )
 
@@ -125,8 +126,8 @@
 func (m *mediator) Start() {
 	var wg sync.WaitGroup
 	opt := m.opt
-	omciOut := make(chan OmciMsg, 8)
-	omciIn := make(chan OmciMsg, 8)
+	omciOut := make(chan openolt.OmciMsg, 1024)
+	omciIn := make(chan openolt.OmciIndication, 1024)
 	go OmciRun(omciOut, omciIn)
 	server := NewCore(opt, omciOut, omciIn)
 	wg.Add(1)
diff --git a/core/omci.go b/core/omci.go
index 8d891dc..f4147dd 100644
--- a/core/omci.go
+++ b/core/omci.go
@@ -17,13 +17,70 @@
 package core
 
 import (
+	"bytes"
+	"encoding/binary"
+
 	"gerrit.opencord.org/voltha-bbsim/common/logger"
+	"gerrit.opencord.org/voltha-bbsim/protos"
 )
 
-type OmciMsg struct {
-	IntfId uint32
-	OnuId  uint32
-	Pkt    []byte
+//
+// OMCI definitions
+//
+
+// OmciMsgType represents a OMCI message-type
+type OmciMsgType byte
+
+const (
+	// Message Types
+	_                                 = iota
+	Create                OmciMsgType = 4
+	Delete                OmciMsgType = 6
+	Set                   OmciMsgType = 8
+	Get                   OmciMsgType = 9
+	GetAllAlarms          OmciMsgType = 11
+	GetAllAlarmsNext      OmciMsgType = 12
+	MibUpload             OmciMsgType = 13
+	MibUploadNext         OmciMsgType = 14
+	MibReset              OmciMsgType = 15
+	AlarmNotification     OmciMsgType = 16
+	AttributeValueChange  OmciMsgType = 17
+	Test                  OmciMsgType = 18
+	StartSoftwareDownload OmciMsgType = 19
+	DownloadSection       OmciMsgType = 20
+	EndSoftwareDownload   OmciMsgType = 21
+	ActivateSoftware      OmciMsgType = 22
+	CommitSoftware        OmciMsgType = 23
+	SynchronizeTime       OmciMsgType = 24
+	Reboot                OmciMsgType = 25
+	GetNext               OmciMsgType = 26
+	TestResult            OmciMsgType = 27
+	GetCurrentData        OmciMsgType = 28
+	SetTable              OmciMsgType = 29 // Defined in Extended Message Set Only
+)
+
+const (
+	// Managed Entity Class values
+	GEMPortNetworkCTP OmciClass = 268
+)
+
+// OMCI Managed Entity Class
+type OmciClass uint16
+
+// OMCI Message Identifier
+type OmciMessageIdentifier struct {
+	Class    OmciClass
+	Instance uint16
+}
+
+type OmciContent [32]byte
+
+type OmciMessage struct {
+	TransactionId uint16
+	MessageType   OmciMsgType
+	DeviceId      uint8
+	MessageId     OmciMessageIdentifier
+	Content       OmciContent
 }
 
 const NumMibUploads byte = 9
@@ -33,42 +90,45 @@
 }
 
 type OnuState struct {
+	gemPortId    uint16
 	mibUploadCtr uint16
 	uniGInstance uint8
 	pptpInstance uint8
 }
 
-func OmciRun(omciOut chan OmciMsg, omciIn chan OmciMsg) {
+var Onus = map[OnuKey]*OnuState{}
 
-	onus := make(map[OnuKey]*OnuState)
+func OmciRun(omciOut chan openolt.OmciMsg, omciIn chan openolt.OmciIndication) {
 
 	for {
-		var resp OmciMsg
+		var resp openolt.OmciIndication
 
 		m := <-omciOut
 
-		msgType, transactionId, meClass, meInstance := ParsePkt(m.Pkt)
+		transactionId, deviceId, msgType, class, instance, content := ParsePkt(m.Pkt)
 
 		logger.Debug("OmciRun - transactionId: %d msgType: %d, ME Class: %d, ME Instance: %d",
-			transactionId, msgType, meClass, meInstance)
+			transactionId, msgType, class, instance)
 
 		key := OnuKey{m.IntfId, m.OnuId}
-		if _, ok := onus[key]; !ok {
-			onus[key] = NewOnuState()
+		if _, ok := Onus[key]; !ok {
+			Onus[key] = NewOnuState()
 		}
 		switch msgType {
-		case 15:
-			resp.Pkt = MibReset()
+		case MibReset:
+			resp.Pkt = mibReset()
 		case 13:
-			resp.Pkt = MibUpload()
+			resp.Pkt = mibUpload()
 		case 14:
-			resp.Pkt = MibUploadNext(onus[key])
+			resp.Pkt = mibUploadNext(Onus[key])
 		case 8:
-			resp.Pkt = Set()
+			resp.Pkt = set()
 		case 4:
-			resp.Pkt = Create()
+			resp.Pkt = create(class, content, key)
 		case 9:
-			resp.Pkt = Get()
+			resp.Pkt = get()
+		case 11:
+			resp.Pkt = getAllAlarms()
 		default:
 			logger.Warn("Omci msg type not handled: %d", msgType)
 			continue
@@ -76,65 +136,81 @@
 
 		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
 	}
 }
 
-func ParsePkt(pkt []byte) (byte, uint16, uint16, uint16) {
+func ParsePkt(pkt []byte) (uint16, uint8, OmciMsgType, OmciClass, uint16, OmciContent) {
+	var m OmciMessage
+
+	r := bytes.NewReader(HexDecode(pkt))
+
+	if err := binary.Read(r, binary.BigEndian, &m); err != nil {
+		logger.Error("binary.Read failed: %s", err)
+	}
+	logger.Debug("OmciRun - TransactionId: %d MessageType: %d, ME Class: %d, ME Instance: %d, Content: %x",
+		m.TransactionId, m.MessageType&0x0F, m.MessageId.Class, m.MessageId.Instance, m.Content)
+
+	return m.TransactionId, m.DeviceId, m.MessageType & 0x0F, m.MessageId.Class, m.MessageId.Instance, m.Content
+
+}
+
+func HexDecode(pkt []byte) []byte {
+	// Convert the hex encoding to binary
+	// TODO - Change openolt adapter to send raw binary instead of hex encoded
 	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
 	}
 	logger.Debug("Omci decoded: %x.", p)
-	msgType := p[2] & 0x0F
-	transactionId := (uint16(p[0]) << 8) | uint16(p[1])
-	meClass := (uint16(p[4]) << 8) | uint16(p[5])
-	meInstance := (uint16(p[6]) << 8) | uint16(p[7])
-	return msgType, transactionId, meClass, meInstance
+	return p
 }
 
 func NewOnuState() *OnuState {
-	return &OnuState{mibUploadCtr: 0, uniGInstance: 1, pptpInstance: 1}
+	return &OnuState{gemPortId: 0, mibUploadCtr: 0, uniGInstance: 1, pptpInstance: 1}
 }
 
-func MibReset() []byte {
+func mibReset() []byte {
 	var pkt []byte
 
 	logger.Debug("Omci MibReset")
 
 	pkt = []byte{
-		0x00, 0x01, 0x2f, 0x0a, 0x00, 0x02, 0x00, 0x00,
+		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, 0x28, 0x1f, 0x75, 0x69, 0xaa}
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
 	return pkt
 }
 
-func MibUpload() []byte {
+func mibUpload() []byte {
 	var pkt []byte
 
 	logger.Debug("Omci MibUpload")
 
 	pkt = []byte{
-		0x00, 0x02, 0x2d, 0x0a, 0x00, 0x02, 0x00, 0x00,
+		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, 0x28, 0x0c, 0x63, 0x21, 0x65}
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
 
 	pkt[9] = NumMibUploads // Number of subsequent MibUploadNext cmds
 
 	return pkt
 }
 
-func MibUploadNext(state *OnuState) []byte {
+func mibUploadNext(state *OnuState) []byte {
 	var pkt []byte
 
 	logger.Debug("Omci MibUploadNext")
@@ -143,31 +219,31 @@
 	case 0:
 		// ANI-G
 		pkt = []byte{
-			0x00, 0x03, 0x2e, 0x0a, 0x00, 0x02, 0x00, 0x00,
+			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, 0x28, 0x2c, 0x4d, 0xa9, 0xc8}
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
 	case 1, 2, 3, 4:
 		// UNI-G
 		pkt = []byte{
-			0x00, 0x04, 0x2e, 0x0a, 0x00, 0x02, 0x00, 0x00,
+			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, 0x28, 0x05, 0x19, 0xae, 0x66}
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
 		pkt[11] = state.uniGInstance // ME Instance
 		state.uniGInstance++
 	case 5, 6, 7, 8:
 		pkt = []byte{
-			0x00, 0x16, 0x2e, 0x0a, 0x00, 0x02, 0x00, 0x00,
+			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, 0x28, 0x6f, 0x10, 0x9b, 0x27}
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
 		pkt[11] = state.pptpInstance // ME Instance
 		state.pptpInstance++
 	default:
@@ -179,50 +255,75 @@
 	return pkt
 }
 
-func Set() []byte {
+func set() []byte {
 	var pkt []byte
 
 	pkt = []byte{
-		0x01, 0x15, 0x28, 0x0a, 0x01, 0x00, 0x00, 0x00,
+		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, 0x28, 0x41, 0xb3, 0x95, 0x12}
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
 
 	logger.Debug("Omci Set")
 
 	return pkt
 }
 
-func Create() []byte {
+func create(class OmciClass, content OmciContent, key OnuKey) []byte {
 	var pkt []byte
 
+	if class == GEMPortNetworkCTP {
+		if onuState, ok := Onus[key]; !ok {
+			logger.Error("ONU Key Error - IntfId: %d, OnuId:", key.IntfId, key.OnuId)
+		} else {
+			onuState.gemPortId = binary.BigEndian.Uint16(content[:2])
+			logger.Debug("Gem Port Id %d", onuState.gemPortId)
+		}
+	}
+
 	pkt = []byte{
-		0x01, 0x17, 0x24, 0x0a, 0x01, 0x10, 0x00, 0x01,
+		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, 0x28, 0x85, 0xcb, 0x98, 0x86}
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
 
 	logger.Debug("Omci Create")
 
 	return pkt
 }
 
-func Get() []byte {
+func get() []byte {
 	var pkt []byte
 
 	pkt = []byte{
-		0x01, 0x26, 0x29, 0x0a, 0x00, 0x2d, 0x02, 0x01,
+		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, 0x28, 0xbc, 0x0c, 0xa4, 0x18}
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
 
 	logger.Debug("Omci Get")
 
 	return pkt
 }
+
+func getAllAlarms() []byte {
+	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
+}