blob: c9860c2d72c88339a2eb30b2c4abcb9a741075ad [file] [log] [blame]
/*
* 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 (
"bytes"
"encoding/binary"
"context"
"errors"
"time"
"gerrit.opencord.org/voltha-bbsim/common/logger"
"gerrit.opencord.org/voltha-bbsim/device"
"gerrit.opencord.org/voltha-bbsim/protos"
)
//
// 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 = 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 OmciRun(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
t := time.NewTicker(1 * time.Second)
defer t.Stop()
for {
select {
case <-t.C:
logger.Debug("Monitor omci init state")
if isAllOmciInitDone(onumap) {
logger.Info("OmciRun - All the omci initialization wes done")
close(errch)
return
}
case <-ctx.Done():
logger.Debug("Omci Monitoring process was done")
return
}
}
}()
go func() {
defer logger.Debug("Omci response process was done")
for {
var resp openolt.OmciIndication
select {
case m := <-omciOut:
transactionId, deviceId, msgType, class, instance, content, err := ParsePkt(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)
continue
}
resp.Pkt, err = Handlers[msgType](class, content, key)
if err != nil {
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
}
}
}()
}
func ParsePkt(pkt []byte) (uint16, uint8, OmciMsgType, OmciClass, uint16, OmciContent, error) {
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)
return 0, 0, 0, 0, 0, OmciContent{}, errors.New("binary.Read failed")
}
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, nil
}
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)
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 {
return false
}
}
}
return true
}