| /* |
| * 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" |
| "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 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(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) |
| 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 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 |
| } |